#include "shell.h"
#include "executesql.h"
#include "BussinessTerminalManage.h"
#include <sys/file.h> 
int g_network_rule_num = 0;
extern ob_context g_mqtt_ob;
//pthread_t thread_lsc;

/**
 * @description: 进程kill解析
 * @param {char} *pcJson
 * @param {ST_IOTA_LOG} *pcStatusDecs
 * @return {*}
 */
bool JsonToStruct_ServiceKill(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        // pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            param = cJSON_GetObjectItem(json, "params");
            IOTA_KILL_PARAM *st_param = pcStatusDecs->param;
            st_param->pid = cJSON_GetObjectItem(param, "pid")->valueint;
        }

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}
/**
 * @description: 服务开关
 * @param {char} *pcJson
 * @param {ST_IOTA_LOG} *pcStatusDecs
 * @return {*}
 */
bool JsonToStruct_ServiceOnOff(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        if (cJSON_HasObjectItem(json, "requestId") && strlen(cJSON_GetObjectItem(json, "requestId")->valuestring) > 0)
        {
            pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        }
        else
        {
            pcStatusDecs->requestID = NULL;
        }
        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            param = cJSON_GetObjectItem(json, "params");
            IOTA_SERVICE_PARAM *st_param = pcStatusDecs->param;
            st_param->service = strdup(cJSON_GetObjectItem(param, "service")->valuestring);
        }

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

bool JsonToStruct_ServiceFirewall(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    cJSON *info = NULL;
    int num = 0;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        // pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        if (cJSON_HasObjectItem(json, "params"))
        {
            int i = 0;
            param = cJSON_GetObjectItem(json, "params");
            num = cJSON_GetArraySize(param);
            dzlog_info("JsonToStruct_ServiceFirewall start 33 num:%d", num);
            PIOTA_NETWORKLIST_PARAM st_param = pcStatusDecs->param;
            for (i = 0; i < num; i++)
            {
                info = cJSON_GetArrayItem(param, i);
                if (cJSON_HasObjectItem(info, "dstIp"))
                {
                    strcpy(st_param->dstIp, cJSON_GetObjectItem(info, "dstIp")->valuestring);
                    dzlog_info("JsonToStruct_ServiceFirewall start 3311 ip:%s", st_param->dstIp);
                }
                if (cJSON_HasObjectItem(info, "dstPort"))
                {
                    strcpy(st_param->dstPort, cJSON_GetObjectItem(info, "dstPort")->valuestring);
                }
                else
                {
                    strcpy(st_param->dstPort, "0");
                }
                if (cJSON_HasObjectItem(info, "srcIp"))
                {
                    strcpy(st_param->srcIp, cJSON_GetObjectItem(info, "srcIp")->valuestring);
                }
                if (cJSON_HasObjectItem(info, "srcPort"))
                {
                    strcpy(st_param->srcPort, cJSON_GetObjectItem(info, "srcPort")->valuestring);
                }
                else
                {
                    strcpy(st_param->srcPort, "0");
                }
                if (cJSON_HasObjectItem(info, "protocol"))
                {
                    strcpy(st_param->protocol, cJSON_GetObjectItem(info, "protocol")->valuestring);
                }
                else
                {
                    strcpy(st_param->protocol, "tcp");
                }
                if (cJSON_HasObjectItem(info, "priority"))
                {
                    st_param->priority = cJSON_GetObjectItem(info, "priority")->valueint;
                }
                else
                {
                    st_param->priority = 1;
                }
                st_param++;
            }
        }

        cJSON_Delete(json);
        return num;
    }
    else
    {
        return num;
    }
}

int JsonToStruct_ServiceFirewall_V1(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *params = NULL;
    int ret = 1;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        if (cJSON_HasObjectItem(json, "params"))
        {
            params = cJSON_GetObjectItem(json, "params");
            if (cJSON_IsArray(params))
            {
                PIOTA_NETWORKLIST_PARAM_V1 st_param = pcStatusDecs->param;
                int i = 0;
                ret = cJSON_GetArraySize(params);
                for (i = 0; i < cJSON_GetArraySize(params); i++)
                {
                    cJSON *info = cJSON_GetArrayItem(params, i);

                    if (cJSON_HasObjectItem(info, "policyId"))
                    {
                        strcpy(st_param->policyId, cJSON_GetObjectItem(info, "policyId")->valuestring);
                    }
                    if (cJSON_HasObjectItem(info, "operation"))
                    {
                        strcpy(st_param->operation, cJSON_GetObjectItem(info, "operation")->valuestring);
                    }
                    if (cJSON_HasObjectItem(info, "permissionStatus"))
                    {
                        strcpy(st_param->permissionStatus, cJSON_GetObjectItem(info, "permissionStatus")->valuestring);
                    }
                    if (cJSON_HasObjectItem(info, "dstIp"))
                    {
                        strcpy(st_param->dstIp, cJSON_GetObjectItem(info, "dstIp")->valuestring);
                    }
                    if (cJSON_HasObjectItem(info, "dstPort"))
                    {
                        strcpy(st_param->dstPort, cJSON_GetObjectItem(info, "dstPort")->valuestring);
                    }
                    else
                    {
                        strcpy(st_param->dstPort, "0");
                    }
                    if (cJSON_HasObjectItem(info, "srcIp"))
                    {
                        strcpy(st_param->srcIp, cJSON_GetObjectItem(info, "srcIp")->valuestring);
                    }
                    if (cJSON_HasObjectItem(info, "srcPort"))
                    {

                        if (strcmp(cJSON_GetObjectItem(info, "srcPort")->valuestring, "*") == 0)
                        {
                            strcpy(st_param->srcPort, "0");
                        }
                        else
                        {
                            strcpy(st_param->srcPort, cJSON_GetObjectItem(info, "srcPort")->valuestring);
                        }
                    }
                    else
                    {
                        strcpy(st_param->srcPort, "0");
                    }
                    if (cJSON_HasObjectItem(info, "protocol"))
                    {
                        strcpy(st_param->protocol, cJSON_GetObjectItem(info, "protocol")->valuestring);
                    }
                    else
                    {
                        strcpy(st_param->protocol, "tcp");
                    }

                    if (cJSON_HasObjectItem(info, "priority"))
                    {
                        st_param->priority = cJSON_GetObjectItem(info, "priority")->valueint;
                    }
                    else
                    {
                        st_param->priority = 1;
                    }
                    st_param++;
                }
            }
            else
            {
                PIOTA_NETWORKLIST_PARAM_V1 st_param = pcStatusDecs->param;
                if (cJSON_HasObjectItem(params, "policyId"))
                {
                    strcpy(st_param->policyId, cJSON_GetObjectItem(params, "policyId")->valuestring);
                }
                if (cJSON_HasObjectItem(params, "operation"))
                {
                    strcpy(st_param->operation, cJSON_GetObjectItem(params, "operation")->valuestring);
                }
                if (cJSON_HasObjectItem(params, "permissionStatus"))
                {
                    strcpy(st_param->permissionStatus, cJSON_GetObjectItem(params, "permissionStatus")->valuestring);
                }
                if (cJSON_HasObjectItem(params, "srcIp"))
                {
                    strcpy(st_param->srcIp, cJSON_GetObjectItem(params, "srcIp")->valuestring);
                }
                if (cJSON_HasObjectItem(params, "srcPort"))
                {
                    strcpy(st_param->srcPort, cJSON_GetObjectItem(params, "srcPort")->valuestring);
                }
                else
                {
                    strcpy(st_param->srcPort, "0");
                }

                if (cJSON_HasObjectItem(params, "protocol"))
                {
                    strcpy(st_param->protocol, cJSON_GetObjectItem(params, "protocol")->valuestring);
                }
                else
                {
                    strcpy(st_param->protocol, "tcp");
                }
                if (cJSON_HasObjectItem(params, "priority"))
                {
                    st_param->priority = cJSON_GetObjectItem(params, "priority")->valueint;
                }
                else
                {
                    st_param->priority = 1;
                }
            }
        }
        cJSON_Delete(json);
        return ret;
    }
    else
    {
        return -1;
    }
}

bool JsonToStruct_ServiceFirewall_V2(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;

    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        cJSON_Delete(json);
        return 1;
    }
    else
    {
        return -1;
    }
}

int JsonToStruct_ServiceFirewall_V3(char* pcJson, ST_IOTA_LOG* pcStatusDecs,int flat)
{
    cJSON* json = NULL;
    cJSON* params = NULL;
    int ret = 0;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        if (flat == 1)
        {
            if (cJSON_HasObjectItem(json, "params"))
            {
                params = cJSON_GetObjectItem(json, "params");
                if (cJSON_IsArray(params))
                {
                    PIOTA_NETWORKLIST_PARAM_V2 st_param = pcStatusDecs->param;
                    int i = 0;
                    ret = cJSON_GetArraySize(params);
                    for (i = 0; i < cJSON_GetArraySize(params); i++)
                    {
                        cJSON* info = cJSON_GetArrayItem(params, i);
                        if (cJSON_HasObjectItem(info, "policyId"))
                        {
                            strcpy(st_param->policyId, cJSON_GetObjectItem(info, "policyId")->valuestring);
                        }
                        if (cJSON_HasObjectItem(info, "operation"))
                        {
                            strcpy(st_param->operation, cJSON_GetObjectItem(info, "operation")->valuestring);
                        }
                        if (cJSON_HasObjectItem(info, "chainDirection"))
                        {
                            strcpy(st_param->chainDirection, cJSON_GetObjectItem(info, "chainDirection")->valuestring);
                        }
                        if (cJSON_HasObjectItem(info, "permissionStatus"))
                        {
                            strcpy(st_param->permissionStatus, cJSON_GetObjectItem(info, "permissionStatus")->valuestring);
                        }
                        if (cJSON_HasObjectItem(info, "protocol"))
                        {
                            strcpy(st_param->protocol, cJSON_GetObjectItem(info, "protocol")->valuestring);
                        }
                        else
                        {
                            strcpy(st_param->protocol, "all");
                        }
                        if (cJSON_HasObjectItem(info, "srcIp"))
                        {
                            strcpy(st_param->srcIp, cJSON_GetObjectItem(info, "srcIp")->valuestring);
                        }
                        else
                        {
                            strcpy(st_param->srcIp,"0.0.0.0");
                        }
                        if (cJSON_HasObjectItem(info, "srcPort"))
                        {
                            char* p = strstr(cJSON_GetObjectItem(info, "srcPort")->valuestring, "*");
                            if (!p)
                            {
                                strcpy(st_param->srcPort, cJSON_GetObjectItem(info, "srcPort")->valuestring);
                            }
                        }
                        if (cJSON_HasObjectItem(info, "dstIp"))
                        {
                            strcpy(st_param->dstIp, cJSON_GetObjectItem(info, "dstIp")->valuestring);
                        }
                        else
                        {
                            strcpy(st_param->dstIp, "0.0.0.0");
                        }
                        if (cJSON_HasObjectItem(info, "dstPort"))
                        {
                            char* p = strstr(cJSON_GetObjectItem(info, "dstPort")->valuestring, "*");
                            if (!p)
                            {
                                strcpy(st_param->dstPort, cJSON_GetObjectItem(info, "dstPort")->valuestring);
                            }
                        }
                        if (cJSON_HasObjectItem(info, "state"))
                        {
                            strcpy(st_param->state, cJSON_GetObjectItem(info, "state")->valuestring);
                        }
                        if (cJSON_HasObjectItem(info, "ruleOrigin"))
                        {
                            st_param->ruleOrigin = cJSON_GetObjectItem(info, "ruleOrigin")->valueint;
                        }
                        else
                        {
                            st_param->ruleOrigin = 2;
                        }
                        if (cJSON_HasObjectItem(info, "priority"))
                        {
                            st_param->priority = cJSON_GetObjectItem(info, "priority")->valueint;
                        }
                        else
                        {
                            st_param->priority = 1;
                        }
                        st_param++;
                    }
                }
            }
        }
        cJSON_Delete(json);
        return ret;
    }
    else
    {
        return -1;
    }
}

int JsonToStruct_ServiceFirewall_V4(char* pcJson, ST_IOTA_LOG* pcStatusDecs)
{
    cJSON* json = NULL;
    cJSON* params = NULL;
    int ret = 0;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            params = cJSON_GetObjectItem(json, "params");
            if (cJSON_IsArray(params))
            {
                PIOTA_NETWORKLIST_PARAM_V3 st_param = pcStatusDecs->param;
                int i = 0;
                ret = cJSON_GetArraySize(params);
                for (i = 0; i < cJSON_GetArraySize(params); i++)
                {
                    cJSON* info = cJSON_GetArrayItem(params, i);
                    if (cJSON_HasObjectItem(info, "policyId"))
                    {
                        strcpy(st_param->policyId, cJSON_GetObjectItem(info, "policyId")->valuestring);
                    }
                    if (cJSON_HasObjectItem(info, "newPrio"))
                    {
                        st_param->newPrio = cJSON_GetObjectItem(info, "newPrio")->valueint;
                    }
                    else
                    {
                        ret = -1;
                    }
                }
            }
        }

        

        cJSON_Delete(json);
        return ret;
    }
    else
    {
        return -1;
    }
}

bool JsonToStruct_ServiceNIC(char *pcJson, ST_IOTA_LOG *pcStatusDecs)
{
    cJSON *json = NULL;
    cJSON *param = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
        pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
        pcStatusDecs->Servicename = strdup(cJSON_GetObjectItem(json, "service")->valuestring);
        pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
        pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
        if (cJSON_HasObjectItem(json, "requestId") && strlen(cJSON_GetObjectItem(json, "requestId")->valuestring) > 0)
        {
            pcStatusDecs->requestID = strdup(cJSON_GetObjectItem(json, "requestId")->valuestring);
        }
        else
        {
            pcStatusDecs->requestID = strdup("com.jxtech.iot_ops - tasks");
        }

        pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
        pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);

        if (cJSON_HasObjectItem(json, "params"))
        {
            param = cJSON_GetObjectItem(json, "params");
            IOTA_NIC_PARAM *st_param = pcStatusDecs->param;
            st_param->iface = strdup(cJSON_GetObjectItem(param, "iface")->valuestring);
        }

        cJSON_Delete(json);
        return true;
    }
    else
    {
        return false;
    }
}

int terminalServiceKill(char *pJson)
{
    ST_IOTA_LOG log;
    IOTA_KILL_PARAM param;
    log.param = &param;
    JsonToStruct_ServiceKill(pJson, &log);

    char *psJson;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.requestID = NULL;
    log_res.zone = log.zone;
    bool isError = false;

    //获取被kill的pid的进程名start---------非业务需求，仅作为操作的记录
    char cmd[100] = { 0 };
    sprintf(cmd, "ps -ef | grep %d", param.pid);
    FILE* fd = popen(cmd, "r");
    if (fd != NULL)
    {
        char buffer[512];
        while (fgets(buffer, sizeof(buffer), fd) != NULL)
        {
            // 处理命令输出
            dzlog_info("killProcess message[%s]", buffer);
        }
        fclose(fd);
    }
    //获取被kill的pid的进程名end


    if (kill(param.pid, SIGKILL) == 0)
    {
        dzlog_info("kill %d success", param.pid);
    }

    else
    {
        int error = errno;
        dzlog_error("kill %d error %s", param.pid, strerror(error));
        // 当进程不存在导致kill失败的时候，也要返回成功 3为找不到进程
        if (error != 3)
        {
            isError = true;
            log_res.code = 500;
            goto Uerror;
        }
    }

    log_res.code = 200;
    StructToJson_LogUploadRes(&psJson, &log_res, true);
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));

Uerror:
    if (isError)
    {
        log_res.body = "update error";
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.msgTime);
    free(log.node);
    // free(log.requestID);
    free(log.Servicename);
    free(log.zone);
    free_s(psJson);
}
/// @brief 服务开关
/// @param pJson
/// @param onoff
/// @return
int terminalServiceOnoff(char *pJson, bool onoff)
{
    ST_IOTA_LOG log;
    IOTA_SERVICE_PARAM param;
    log.param = &param;
    JsonToStruct_ServiceOnOff(pJson, &log);

    char *psJson = NULL;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.requestID = log.requestID;
    log_res.zone = log.zone;

    log_res.code = 100;
    StructToJson_LogUploadRes(&psJson, &log_res, true);
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    free_s(psJson); //要释放掉，因为后续还要用这个变量，不释放会导致这次的分配内存泄露

    bool isError = false;

    FILE *service = NULL;
    char Lservice[64] = {0};

    if (onoff)
    {
        sprintf(Lservice, "systemctl start %s", param.service);
    }
    else
    {
        sprintf(Lservice, "systemctl stop %s", param.service);
    }
    dzlog_info("terminalServiceOnoff Lservice:%s", Lservice);
    service = popen(Lservice, "r");
    if (service == NULL)
    {
        int error = errno;
        dzlog_error("popen errror:%s", strerror(error));
        isError = true;
        log_res.code = 500;
        goto Uerror;
    }
    char buffer[128];
    while (fgets(buffer, sizeof(buffer), service) != NULL)
    {
        // 处理命令输出
        dzlog_info("message = %s", buffer);
    }
    log_res.code = 200;
    StructToJson_LogUploadRes(&psJson, &log_res, true);
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));

Uerror:
    if (isError)
    {
        log_res.body = "update error";
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.msgTime);
    free(log.node);
    free_s(log.requestID);
    free(log.Servicename);
    free(log.zone);
    free(param.service);
    free_s(psJson);
    pclose(service);
}

/**
 * @brief Set the Firewall Rule object
 * 新增防火墙规则 ps：可以用libptc库和iptables.h头文件，但编译条件过于繁琐，所以出此方案
 * @param remoteIP 远程ip
 * @param remotePort 远程端口
 * @param localIP 本地ip
 * @param localPort 本地端口
 * @param action 进入黑白名单
 */
int setFirewallRule(IOTA_NETWORKLIST_PARAM param, char *action)
{
    dzlog_info("setFirewallRule start 11");
    char command[200];

    sprintf(command, "iptables -I INPUT -p %s ", param.protocol); // param.priority这个字段不一定会传
    // sprintf(command, "iptables -I INPUT %d -p %s ", param.priority, param.protocol);
    dzlog_info("setFirewallRule start 22 command:%s", command);

    if (strlen(param.dstIp) > 0)
    {
        dzlog_info("setFirewallRule start 22 00 param.dstIp :%s", param.dstIp);
        // sprintf(command, "%s -s %s ", command, param.dstIp);
        strcat(command, " -s ");
        strcat(command, param.dstIp);
    }
    if (atoi(param.dstPort) > 0)
    {
        dzlog_info("setFirewallRule start 22 11 param.dstPort :%s", param.dstPort);
        // sprintf(command, "%s --dport %d", command, param.dstPort);
        strcat(command, " --dport ");
        char temp[16] = {0};
        sprintf(temp, "%s", param.dstPort);
        strcat(command, temp);
    }
    if (strlen(param.srcIp) > 0)
    {
        dzlog_info("setFirewallRule start 22 22 param.srcIp :%s", param.srcIp);
        // sprintf(command, "%s -d %s", command, param.srcIp);
        strcat(command, " -d ");
        strcat(command, param.srcIp);
    }
    if (atoi(param.srcPort) > 0)
    {
        dzlog_info("setFirewallRule start 22 33 param.srcPort :%s", param.srcPort);
        // sprintf(command, "%s --sport %d", command, param.srcPort);
        strcat(command, " --sport ");
        char temp[16] = {0};
        sprintf(temp, "%s", param.srcPort);
        strcat(command, temp);
    }

    // sprintf(command, "%s -j %s", command, action);
    strcat(command, " -j ");
    strcat(command, action);
    dzlog_info("setFirewallRule start 33 command:%s", command);
    FILE *fp = popen(command, "r");
    if (fp == NULL)
    {
        dzlog_error("Failed to execute command setFirewallRule");
        return -1;
    }

    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        dzlog_info("commond: %s", buffer);
    }

    pclose(fp);
    // 保存到文件
    struct stat buffertemp;
    const char *file_path = "/etc/config/iptables";

    if (stat(file_path, &buffertemp) == -1)
    {
        // 文件不存在，创建文件
        FILE *file = fopen(file_path, "w");
        if (file == NULL)
        {
            printf("创建文件失败");
            return 1;
        }
        fclose(file);
        printf("文件已创建");
    }
    else
    {
        printf("文件已存在");
    }
    system("iptables-save > /etc/config/iptables");
    return 0;
}

/* *
 * @brief Set the Firewall Rule object
 * 新增防火墙规则 ps：可以用libptc库和iptables.h头文件，但编译条件过于繁琐，所以出此方案
 * @param remoteIP 远程ip
 * @param remotePort 远程端口
 * @param localIP 本地ip
 * @param localPort 本地端口
 * @param action 进入黑白名单
 * */
int setFirewallRule_V1(IOTA_NETWORKLIST_PARAM_V1 param, char *cmd)
{
    char command[200];
    if (strncmp("ADD", cmd, 3) == 0)
    {
        if (param.priority == 1)
        {
            sprintf(command, "iptables -I INPUT ");
        }
        else
        {
            sprintf(command, "iptables -A INPUT ");
        }
        if (param.protocol != NULL && strlen(param.protocol) != 0)
        {
            char temp[16] = {0};
            sprintf(temp, "-p %s ", param.protocol);
            strcat(command, temp);
        }
    }
    else if (strncmp("DELETE", param.operation, 6) == 0)
    {
        if (param.protocol != NULL && strlen(param.protocol) != 0)
        {
            sprintf(command, "iptables -D INPUT -p %s ", param.protocol);
        }
        else
        {
            sprintf(command, "iptables -D INPUT ");
        }
    }
    dzlog_debug("setFirewallRule_V1 start 22 command:%s", command);

    if (strlen(param.srcIp) > 0)
    {
        if (strncmp("0.0.0.0", param.srcIp, 7) == 0)
        {
            dzlog_debug("setFirewallRule_V1 start 22 22 param.srcIp :%s", param.srcIp);
            strcat(command, " -s ");
            strcat(command, "0.0.0.0/0");
        }
        else
        {
            strcat(command, " -s ");
            strcat(command, param.srcIp);
        }
    }

    if (atoi(param.srcPort) > 0)
    {
        strcat(command, " -m multiport"); //-m multiport 模板
        dzlog_debug("setFirewallRule_V1 start 22 33 param.srcPort :%s", param.srcPort);
        strcat(command, " --sport ");
        char temp[16] = {0};
        sprintf(temp, "%s", param.srcPort);
        strcat(command, temp);
    }

    if (param.dstIp != NULL && strlen(param.dstIp) > 0)
    {
        if (strncmp("0.0.0.0", param.dstIp, 7) == 0)
        {
            dzlog_debug("setFirewallRule_V1 start 22 22 param.dstIp :%s", param.dstIp);
            strcat(command, " -d ");
            strcat(command, "0.0.0.0/0");
        }
        else
        {
            strcat(command, " -d ");
            strcat(command, param.dstIp);
        }
    }
    if (param.dstPort != NULL && atoi(param.dstPort) > 0)
    {
        strcat(command, " -m multiport"); //-m multiport 模板
        dzlog_debug("setFirewallRule_V1 start 22 33 param.dstPort :%s", param.dstPort);
        strcat(command, " --dport ");
        char temp[16] = {0};
        sprintf(temp, "%s", param.dstPort);
        strcat(command, temp);
    }
    strcat(command, " -j ");
    strcat(command, param.permissionStatus);
    dzlog_info("setFirewallRule_V1 start command[%s]", command);

    FILE *fp = popen(command, "r");
    if (fp == NULL)
    {
        dzlog_error("Failed to execute command setFirewallRule_V1");
        return -1;
    }

    ///
    if (strncmp("DROP", param.permissionStatus, 4) == 0)
    {

        if (atoi(param.srcPort) > 0)
        {
            dzlog_info("setFirewallRule_V1 test 1 param.srcPort[%s]", param.srcPort);
            char cmd3[200];
            
            sprintf(cmd3, "netstat -atnp | awk '$4 ~ /:%s$/'", param.srcPort);
            FILE *fp1 = popen(cmd3, "r");
            if (fp1 == NULL)
            {
                dzlog_error("Failed to execute command fp1 setFirewallRule_V1");
                // return -1;
            }
            char buffer1[1024];
            while (fgets(buffer1, sizeof(buffer1), fp1) != NULL)
            {
                dzlog_info("setFirewallRule_V1 start 99 buffer1[%s]", buffer1);
                char *token = strtok(buffer1, " ");
                while (token != NULL)
                {
                    dzlog_info("setFirewallRule_V1 start 99 token[%s]", token);
                    char *p = strstr(token, "/");
                    if (p)
                    {
                        dzlog_info("setFirewallRule_V1 start 1010");
                        char *slash = strchr(token, '/');
                        if (slash != NULL)
                        {
                            int length = slash - token;
                            char result[length + 1];
                            strncpy(result, token, length);
                            result[length] = '\0';
                            printf("截取的值为： %d", atoi(result));
                            dzlog_info("setFirewallRule_V1 start 111[%d]", atoi(result));
                            char cmd4[200];
                            sprintf(cmd4, "kill -9 %d", atoi(result));
                            system(cmd4);
                        }
                        else
                        {
                            printf("未找到斜杠字符");
                        }
                    }
                    token = strtok(NULL, " ");
                }
            }
            pclose(fp1);
        }
        else if (atoi(param.dstPort) > 0)
        {
            dzlog_info("setFirewallRule_V1 start 88");
            char cmd3[200];
            sprintf(cmd3, "netstat -atnp | awk '$4 ~ /:%s$/'", param.dstPort);
            FILE *fp1 = popen(cmd3, "r");
            if (fp1 == NULL)
            {
                dzlog_error("Failed to execute command fp1 setFirewallRule_V1");
                // return -1;
            }
            char buffer1[1024];
            while (fgets(buffer1, sizeof(buffer1), fp1) != NULL)
            {
                dzlog_info("setFirewallRule_V1 start 99 buffer1[%s]", buffer1);
                char *token = strtok(buffer1, " ");
                while (token != NULL)
                {
                    dzlog_info("setFirewallRule_V1 start 99 token[%s]", token);
                    char *p = strstr(token, "/");
                    if (p)
                    {
                        dzlog_info("setFirewallRule_V1 start 1010");
                        char *slash = strchr(token, '/');
                        if (slash != NULL)
                        {
                            int length = slash - token;
                            char result[length + 1];
                            strncpy(result, token, length);
                            result[length] = '\0';
                            printf("截取的值为： %d", atoi(result));
                            dzlog_info("setFirewallRule_V1 start 111[%d]", atoi(result));
                            char cmd4[200];
                            sprintf(cmd4, "kill -9 %d", atoi(result));
                            system(cmd4);
                        }
                        else
                        {
                            printf("未找到斜杠字符");
                        }
                    }
                    token = strtok(NULL, " ");
                }
            }
            pclose(fp1);
        }
    }
    ///

    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        dzlog_info("buffer: %s", buffer);
    }

    pclose(fp);

    //// 保存到文件
    //struct stat buffertemp;
    //const char *file_path = "/etc/config/iptables";
    //if (stat(file_path, &buffertemp) == -1)
    //{
    //    // 文件不存在，创建文件
    //    FILE *file = fopen(file_path, "w");
    //    if (file == NULL)
    //    {
    //        printf("创建文件失败");
    //        return 1;
    //    }
    //    fclose(file);
    //    printf("文件已创建");
    //}
    //else
    //{
    //    printf("文件已存在");
    //}
    //system("iptables-save > /etc/config/iptables");
    return 0;
}

/**
 * @param remoteIP 远程ip
 * @param remotePort 远程端口
 * @param localIP 本地ip
 * @param localPort 本地端口
 * @param action 进入黑白名单
 */
int setFirewallRule_V2(IOTA_NETWORKLIST_PARAM_V2 param, char* cmd, CommunicationMode mode,int setprio)
{

    char command[200];
    bool addflag = false;
    dzlog_info("setFirewallRule_V2 start 1 setprio[%d]",setprio);
    //1.给command设置操作类型
    if (strncmp("ADD", cmd, 3) == 0)
    {
        //priority,插队头还是插队尾
        if (param.priority == 1)
        {
            sprintf(command, "iptables -I ");

        }
        else
        {
            sprintf(command, "iptables -A ");
        }
        addflag = true;
    }
    else if (strncmp("DELETE", cmd, 6) == 0)
    {
        sprintf(command, "iptables -D ");
    }
    else if (strncmp("UPDATE", cmd, 6) == 0)
    {
        sprintf(command, "iptables -R ");
    }
    dzlog_info("setFirewallRule_V2 start 2");
    //2.给command设置针对的规则链名
    if (param.chainDirection != NULL && strlen(param.chainDirection) != 0)
    {
        char temp[16] = { 0 };
        sprintf(temp, "%s", param.chainDirection);
        strcat(command, temp);
    }
    dzlog_info("setFirewallRule_V2 start 3");
    if (setprio != 0)
    {
        char temp[8] = { 0 };
        sprintf(temp, " %d ", setprio);
        strcat(command, temp);
    }
    


    bool srcip_range_flag = false;
    bool dstip_range_flag = false;
    if (param.srcIp != NULL && strlen(param.srcIp) != 0)
    {
        if (strchr(param.srcIp, '-') != NULL){ srcip_range_flag = true; }
    }
    if (param.dstIp != NULL && strlen(param.dstIp) != 0)
    {
        if (strchr(param.dstIp, '-') != NULL){ dstip_range_flag = true; }
    }
    if (srcip_range_flag || dstip_range_flag)
    {
        strcat(command, " -m iprange ");
    }

    //3.给command设置源ip
    if (strlen(param.srcIp) > 0)
    {
        if (srcip_range_flag)
        {
            strcat(command, " --src-range ");
            strcat(command, param.srcIp);
        }
        else
        {
            if (strncmp("0.0.0.0", param.srcIp, 7) == 0)
            {
                strcat(command, " -s ");
                strcat(command, "0.0.0.0/0");
            }
            else
            {
                strcat(command, " -s ");
                strcat(command, param.srcIp);
            }
        } 
    }

    //4.给command设置目标ip
    if (param.dstIp != NULL && strlen(param.dstIp) > 0)
    {
        if (srcip_range_flag)
        {
            strcat(command, " --dst-range ");
            strcat(command, param.dstIp);
        }
        else
        {
            if (strncmp("0.0.0.0", param.dstIp, 7) == 0)
            {
                strcat(command, " -d ");
                strcat(command, "0.0.0.0/0");
            }
            else
            {
                strcat(command, " -d ");
                strcat(command, param.dstIp);
            }
        }
    }

    //5.给command设置协议
    if (param.protocol != NULL && strlen(param.protocol) != 0)
    {
        char temp[16] = { 0 };
        sprintf(temp, " -p %s", param.protocol);
        strcat(command, temp);
    }

    //strcat(command, " -m multiport "); //-m multiport 模板
    if (mode == SINGLE_SOURCE_SINGLE_DEST)
    {
        //给command设置单个或者连续范围源端口
        if (param.srcPort != NULL && strlen(param.srcPort)>0)
        {
            strcat(command, " --sport ");
            strcat(command, param.srcPort);
        }
        //给command设置单个或者连续范围目标端口
        if (param.dstPort != NULL && strlen(param.dstPort) > 0)
        {
            strcat(command, " --dport ");
            strcat(command, param.dstPort);
        }
    }
    else if (mode == MULTI_SOURCE_SINGLE_DEST)//多源端口匹配单个或者连续范围目标端口
    {
        //给command设置单个或者连续范围目标端口
        if (param.dstPort != NULL && strlen(param.dstPort) > 0)
        {
            strcat(command, " --dport ");
            strcat(command, param.dstPort);
        }
        //给command设置多个零散源端口
        strcat(command, " -m multiport --sports ");
        strcat(command, param.srcPort);
    }
    else if (mode == SINGLE_SOURCE_MULTI_DEST)//单个或者连续范围源端口匹配多目标端口
    {
        //给command设置单个或者连续范围源端口
        if (param.srcPort != NULL && strlen(param.srcPort) > 0)
        {
            strcat(command, " --sport ");
            strcat(command, param.srcPort);
        }
        //给command设置多个零散目标端口
        strcat(command, " -m multiport --dports ");
        strcat(command, param.dstPort);
    }
    else
    {
        //明确指令不支持
    }

    //8.给command设置state
    if (param.state != NULL && strlen(param.state) > 0)
    {
        strcat(command, " -m state --state ");
        char temp[16] = { 0 };
        sprintf(temp, "%s", param.state);
        strcat(command, temp);
    }
    //9.给command设置是否封禁
    strcat(command, " -j ");
    strcat(command, param.permissionStatus);
    strcat(command, " 2>&1");

    dzlog_info("setFirewallRule_V2 start command[%s]", command);

    FILE* fp = popen(command, "r");
    if (fp == NULL)
    {
        dzlog_error("Failed to execute command setFirewallRule_V1");
        return -1;
    }
    int ret = 0;
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        ret = -1;
        dzlog_info("commond:[%s]", buffer);
        if (strlen(buffer) > 0)//发生错误
        {
            dzlog_info("commond1");
            if (strstr(buffer, "iprange") != NULL)
            { 
                //不支持iprange
                ret = -2;
                dzlog_info("commond 2");
                break;
            }
            else if (strstr(command, "-D") != NULL)
            {
                //删除报错，理论上，只会是平台新增的策略然后控制台执行-D删除后，平台删除才会报错。
                ret = 0;
                dzlog_info("commond 3");
                break;
            }
            else
            {
                //其他错误
                ret = -1;
                dzlog_info("commond 4");
                break;
            }
        }
    }
    dzlog_info("commond 5");
    pclose(fp);
    dzlog_info("commond 6");
    if (ret < 0)
    {
        return ret;
    }


    if (strcmp(param.operation, "DELETE") != 0)
    {
        //10.当是封禁的时候，把涉及的进程kill掉
        if (strncmp("DROP", param.permissionStatus, 4) == 0)
        {
            bool srcPortneedtokill = false;
            bool dstPortneedtokill = false;
            if (param.srcPort != NULL && strlen(param.srcPort) != 0)
            {
                if (strchr(param.srcPort, ',') != NULL || strchr(param.srcPort, ':') != NULL)
                {
                    srcPortneedtokill = false;
                }
                else
                {
                    if (atoi(param.srcPort) > 0 && atoi(param.srcPort) != 35520)
                    {
                        srcPortneedtokill = true;
                    }
                }
            }
            if (param.dstPort != NULL && strlen(param.dstPort) != 0)
            {
                if (strchr(param.dstPort, ',') != NULL || strchr(param.dstPort, ':') != NULL)
                {
                    dstPortneedtokill = false;
                }
                else
                {
                    if (atoi(param.dstPort) > 0 && atoi(param.dstPort) != 35520)
                    {
                        dstPortneedtokill = true;
                    }
                }
            }
            if (srcPortneedtokill)
            {
                dzlog_info("setFirewallRule_V1 test 1 param.srcPort[%s]", param.srcPort);
                char cmd3[200];

                sprintf(cmd3, "netstat -atnp | awk '$4 ~ /:%s$/'", param.srcPort);
                FILE* fp1 = popen(cmd3, "r");
                if (fp1 == NULL)
                {
                    dzlog_error("Failed to execute command fp1 setFirewallRule_V1");
                    // return -1;
                }
                char buffer1[1024];
                while (fgets(buffer1, sizeof(buffer1), fp1) != NULL)
                {
                    dzlog_info("setFirewallRule_V1 start 99 buffer1[%s]", buffer1);
                    char* token = strtok(buffer1, " ");
                    while (token != NULL)
                    {
                        dzlog_info("setFirewallRule_V1 start 99 token[%s]", token);
                        char* p = strstr(token, "/");
                        if (p)
                        {
                            dzlog_info("setFirewallRule_V1 start 1010");
                            char* slash = strchr(token, '/');
                            if (slash != NULL)
                            {
                                int length = slash - token;
                                char result[length + 1];
                                strncpy(result, token, length);
                                result[length] = '\0';
                                printf("截取的值为： %d", atoi(result));
                                dzlog_info("setFirewallRule_V1 start 111[%d]", atoi(result));
                                if (atoi(result) > 2000)
                                {
                                    char cmd4[64];
                                    sprintf(cmd4, "kill -9 %d", atoi(result));
                                    system(cmd4);
                                }
                            }
                            else
                            {
                                printf("未找到斜杠字符");
                            }
                        }
                        token = strtok(NULL, " ");
                    }
                }
                pclose(fp1);
            }


            if (dstPortneedtokill)
            {
                dzlog_info("setFirewallRule_V1 start 88");
                char cmd3[200];
                sprintf(cmd3, "netstat -atnp | awk '$4 ~ /:%s$/'", param.dstPort);
                FILE* fp1 = popen(cmd3, "r");
                if (fp1 == NULL)
                {
                    dzlog_error("Failed to execute command fp1 setFirewallRule_V1");
                    // return -1;
                }
                char buffer1[1024];
                while (fgets(buffer1, sizeof(buffer1), fp1) != NULL)
                {
                    dzlog_info("setFirewallRule_V1 start 99 buffer1[%s]", buffer1);
                    char* token = strtok(buffer1, " ");
                    while (token != NULL)
                    {
                        dzlog_info("setFirewallRule_V1 start 99 token[%s]", token);
                        char* p = strstr(token, "/");
                        if (p)
                        {
                            dzlog_info("setFirewallRule_V1 start 1010");
                            char* slash = strchr(token, '/');
                            if (slash != NULL)
                            {
                                int length = slash - token;
                                char result[length + 1];
                                strncpy(result, token, length);
                                result[length] = '\0';
                                printf("截取的值为： %d", atoi(result));
                                dzlog_info("setFirewallRule_V1 start 111[%d]", atoi(result));
                                if (atoi(result) > 2000)
                                {
                                    char cmd4[64];
                                    sprintf(cmd4, "kill -9 %d", atoi(result));
                                    system(cmd4);
                                }
                            }
                            else
                            {
                                printf("未找到斜杠字符");
                            }
                        }
                        token = strtok(NULL, " ");
                    }
                }
                pclose(fp1);
            }
        }
    }

    return ret;
}

/**
 * @brief 删除规则
 *
 * @param remoteIP 远程ip
 * @param remotePort 远程端口
 * @param localIP 本地ip
 * @param localPort 本地端口
 */
int deleteFirewallRule(const char *remoteIP, int remotePort, const char *localIP, int localPort)
{
    char command[200];
    sprintf(command, "iptables -D INPUT -s %s -p tcp --dport %d -d %s --sport %d", remoteIP, remotePort, localIP, localPort);

    FILE *fp = popen(command, "r");
    if (fp == NULL)
    {
        dzlog_error("Failed to execute command deleteFirewallRule");
        return -1;
    }

    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        dzlog_info("commond: %s", buffer);
    }

    pclose(fp);
    return 0;
}
/**
 * @brief 设置端口
 *
 * @param port
 */
int setPort(int port, const char *action)
{
    char command[100];
    sprintf(command, "iptables -A INPUT -p tcp --dport %d -j %s", port, action);

    FILE *fp = popen(command, "r");
    if (fp == NULL)
    {
        dzlog_error("Failed to execute command disablePort");
        return -1;
    }

    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        dzlog_info("commond: %s", buffer);
    }

    pclose(fp);
    return 0;
}

/// @brief 设置防火墙
/// @param pJson
/// @param action 加入黑白名单
/// @return
int setFireWallList(char *pJson, const char *action)
{
    ST_IOTA_LOG log;
    dzlog_info("setFireWallList start 11");
    IOTA_NETWORKLIST_PARAM param[30] = {0};
    memset(param, 0, sizeof(IOTA_NETWORKLIST_PARAM) * 30);
    log.param = &param;
    dzlog_info("setFireWallList start 22");
    int num = JsonToStruct_ServiceFirewall(pJson, &log);
    dzlog_info("setFireWallList start 33");

    // 清空规则表.由于后台每次下发规则总是下发全量，所以每次都是先清空表再写入
    if (g_network_rule_num == 0)
    {
        g_network_rule_num = 1;
        //
        char command[32];
        sprintf(command, "iptables -F INPUT");
        FILE *fp = popen(command, "r");
        if (fp == NULL)
        {
            dzlog_error("Failed to setFireWallList iptables -F INPUT");
            pclose(fp);
            return -1;
        }
        pclose(fp);
    }
    else
    {
        g_network_rule_num = 0;
    }
    // end

    char *psJson = NULL;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.requestID = NULL;
    log_res.zone = log.zone;
    bool isError = false;
    dzlog_info("setFireWallList start 44 num:%d", num);
    int i = 0;

    for (; i < num; i++)
    {
        if (setFirewallRule(param[i], action) >= 0)
        {
            log_res.code = 200;
            dzlog_info("set firewall success dstip = %s, dstport = %s", param[i].dstIp, param[i].dstPort);
        }
        else
        {
            int error = errno;
            log_res.code = 500;
            dzlog_error("set firewall %d error %s", param[i].dstIp, strerror(error));
            isError = true;
        }
    }
    if (!isError)
    {
        log_res.code = 200;
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }
    dzlog_info("setFireWallList start 55");
Uerror:
    if (isError)
    {
        log_res.body = "update error";
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.msgTime);
    free(log.node);
    // free(log.requestID);
    free(log.Servicename);
    free(log.zone);
    free_s(psJson);
}

/**
 * @brief 封禁网卡
 *
 * @param pJson
 * @return int
 */
int setNIC(char *pJson, const char *action)
{
    ST_IOTA_LOG log;
    IOTA_NIC_PARAM param;
    log.param = &param;
    JsonToStruct_ServiceNIC(pJson, &log);

    char *psJson = NULL;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.requestID = log.requestID;
    log_res.zone = log.zone;
    bool isError = false;

    char command[100] = {0};
    sprintf(command, "iptables -A INPUT -i %s -j %s", param.iface, action);
    FILE *fp = popen(command, "r");
    if (fp == NULL)
    {
        int error = errno;
        dzlog_error("popen errror:%s", strerror(error));
        isError = true;
        log_res.code = 500;
        goto Uerror;
    }

    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), fp) != NULL)
    {
        // 处理命令输出
        dzlog_info("message = %s", buffer);
    }
    pclose(fp);
    log_res.code = 200;
    StructToJson_LogUploadRes(&psJson, &log_res, true);
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));

Uerror:
    if (isError)
    {
        log_res.body = "update error";
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.msgTime);
    free(log.node);
    free(log.requestID);
    free(log.Servicename);
    free(log.zone);
    free(param.iface);
    free_s(psJson);

    return 0;
}

/// @brief 设置防火墙-新接口
/// @param pJson
/// @param action 加入黑白名单
/// @return
int setNetworkPolicy(char *pJson)
{
    ST_IOTA_LOG log;
    IOTA_NETWORKLIST_PARAM_V1 param[2] = {0};
    log.param = &param;
    int num = JsonToStruct_ServiceFirewall_V1(pJson, &log);

    char *psJson = NULL;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.zone = log.zone;
    log_res.requestID = NULL;
    bool isError = false;
    int i = 0;
    for (i = 0; i < num; i++)
    {
        if (strncmp("ADD", param[i].operation, 3) == 0)
        {
            //增加一个查表动作，对比表已有数据，是否有相同的，有则不再增加
            int ii = 0;
            ii = SqlSearNetworkPolicyCOUNT_V1(&param[i]);
            dzlog_info("setNetworkPolicy start  ii[%d]", ii);
            if (ii <= 0)
            {
                if (setFirewallRule_V1(param[i], param[i].operation) >= 0)
                {
                    log_res.code = 200;
                    // 往表插记录
                    int remsg = SqlINSERTIntoNetworkPolicy(&param[i]);
                }
                else
                {
                    int error = errno;
                    log_res.code = 500;
                    dzlog_error("setNetworkPolicy set firewall  error %s", strerror(error));
                    isError = true;
                }
            }
        }
        else if (strncmp("DELETE", param[i].operation, 6) == 0)
        {
            if (setFirewallRule_V1(param[i], param[i].operation) >= 0)
            {
                log_res.code = 200;
                // 往表插记录
                int remsg = SqlDeleteNetworkPolicy(param[i].policyId);
            }
            else
            {
                int error = errno;
                log_res.code = 500;
                dzlog_error("setNetworkPolicy DELETE firewall %d error %s", param[i].srcIp, strerror(error));
                isError = true;
            }
        }
        else if (strncmp("UPDATE", param[i].operation, 6) == 0)
        {
            // 先查表，然后删策略，再删记录。再加，再插记录
            IOTA_NETWORKLIST_PARAM_V1 inputpar = {0};
            SqlSearNetworkPolicyById(param[i].policyId, &inputpar);
            if (setFirewallRule_V1(inputpar, "DELETE") >= 0)
            {
                log_res.code = 200;
                // 往表插记录
                int remsg = SqlDeleteNetworkPolicy(param[i].policyId);
            }
            else
            {
                int error = errno;
                log_res.code = 500;
                dzlog_error("setNetworkPolicy set firewall %d error %s", param[i].srcIp, strerror(error));
                isError = true;
            }
            if (setFirewallRule_V1(param[i], "ADD") >= 0)
            {
                log_res.code = 200;
                // 往表插记录
                int remsg = SqlINSERTIntoNetworkPolicy(&param[i]);
            }
            else
            {
                int error = errno;
                log_res.code = 500;
                dzlog_error("setNetworkPolicy set firewall %d error %s", param[i].srcIp, strerror(error));
                isError = true;
            }
        }
        else
        {
            dzlog_error("setNetworkPolicy set firewall 7 operation[%s]", param[i].operation);
            log_res.code = 500;
            isError = true;
        }
    }

    if (!isError)
    {
        log_res.code = 200;
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        char uuid[64] = {0};
        GF_GetGUID(uuid);
        int ret = terminalnetstatEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1);
    }
Uerror:
    if (isError)
    {
        //log_res.body = "update error";
        StructToJson_LogUploadRes(&psJson, &log_res, true);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.node);
    free(log.zone);
    free_s(psJson);

    return 0;
}

int getUpToDateNetworkPolicy(PIOTA_NETWORKLIST_PARAM_V1 param)
{
    int re = 0;
    system("iptables-save > /etc/config/iptables");

    FILE *fp = fopen("/etc/config/iptables", "r");
    if (fp == NULL)
    {
        perror("打开文件失败");
        return -1;
    }
    char line[1024];
    int isfilter = -1;
    char p = NULL;
    while (fgets(line, sizeof(line), fp) != NULL)
    {
        if (isfilter != 1)
        {
            p = strstr(line, "*filter");
            if (p)
            {
                isfilter = 1;
            }
        }
        if (isfilter != 1)
        {
            continue;
        }
        char *token = NULL;
        p = strstr(line, "-A INPUT");
        if (p)
        {
            dzlog_info("getUpToDateNetworkPolicy line[%s]", line);
            // 找到规则链所在行
            token = strtok(line, " ");
            while (token != NULL)
            {
                if (strstr(token, "-s"))
                {
                    dzlog_info("getUpToDateNetworkPolicy -s b token[%s]", token);
                    token = strtok(NULL, " ");
                    dzlog_info("getUpToDateNetworkPolicy -s a token[%s]", token);
                    strcpy(param->srcIp, token);
                }
                else if (strstr(token, "-p"))
                {
                    dzlog_info("getUpToDateNetworkPolicy -p b token[%s]", token);
                    token = strtok(NULL, " ");
                    dzlog_info("getUpToDateNetworkPolicy -p a token[%s]", token);
                    strcpy(param->protocol, token);
                }
                else if (strstr(token, "--sport"))
                {
                    dzlog_info("getUpToDateNetworkPolicy --sport b token[%s]", token);
                    token = strtok(NULL, " ");
                    dzlog_info("getUpToDateNetworkPolicy --sport a token[%s]", token);
                    strcpy(param->srcPort, token);
                }
                else if (strstr(token, "--j"))
                {
                    dzlog_info("getUpToDateNetworkPolicy --j b token[%s]", token);
                    token = strtok(NULL, " ");
                    dzlog_info("getUpToDateNetworkPolicy --j a token[%s]", token);
                    strcpy(param->permissionStatus, token);
                }
                token = strtok(NULL, " ");
                dzlog_info("getUpToDateNetworkPolicy end token[%s]", token);
            }
            param++;
            re++;
        }
    }
    fclose(fp);
    return re;
}

// 查询设备最新的网络策略，并更新至db
int has_duplicate_records(PIOTA_NETWORKLIST_PARAM_V1 input1, int input2)
{
    int re = 0;
    int i = 0;
    for (i = 0; i < input2; i++)
    {
        if (input1->srcIp != NULL && strlen(input1->srcIp) != 0)
        {
            if (input1->srcPort != NULL && strlen(input1->srcPort) != 0)
            {
                bool hasduplicate = SqlSearNetworkPolicyByAll(input1);
                if (!hasduplicate)
                {
                    // 生成id
                    unsigned long long ranom_number = generate_random_number();
                    dzlog_info("random num [%llu]", ranom_number);
                    sprintf(input1->policyId, "%llu", ranom_number);
                    // 插表
                    SqlINSERTIntoNetworkPolicy(input1);
                    sleep(1);
                }
            }
            else
            {
                bool hasduplicate = SqlSearNetworkPolicyWithOutPort(input1);
                if (!hasduplicate)
                {
                    // 生成id
                    unsigned long long ranom_number = generate_random_number();
                    dzlog_info("random num [%llu]", ranom_number);
                    sprintf(input1->policyId, "%llu", ranom_number);
                    // 插表
                    SqlINSERTIntoNetworkPolicy(input1);
                    sleep(1);
                }
            }
        }
        input1++;
    }
    return re;
}

int getNetworkPolicy(char *pJson)
{
    dzlog_info("getNetworkPolicy start 11");
    ST_IOTA_LOG log;

    dzlog_info("getNetworkPolicy start 22");
    JsonToStruct_ServiceFirewall_V2(pJson, &log);
    dzlog_info("getNetworkPolicy start 33");

    PIOTA_NETWORKLIST_PARAM_V1 inputpar1 = (PIOTA_NETWORKLIST_PARAM_V1)malloc(sizeof(IOTA_NETWORKLIST_PARAM_V1) * 50);
    memset(inputpar1, 0, sizeof(IOTA_NETWORKLIST_PARAM_V1) * 50);
    int re = getUpToDateNetworkPolicy(inputpar1);
    dzlog_info("getNetworkPolicy start 3311 re[%d]", re);
    int i = 0;
    for (i = 0; i < re; i++)
    {
        has_duplicate_records(inputpar1, re);
    }
    free(inputpar1);

    int num = SqlSearNetworkPolicyCOUNT();
    dzlog_info("getNetworkPolicy start 3322 num[%d]", num);
    PIOTA_NETWORKLIST_PARAM_V1 inputpar = (PIOTA_NETWORKLIST_PARAM_V1)malloc(sizeof(IOTA_NETWORKLIST_PARAM_V1) * (num + 1));
    SqlSearNetworkPolicy(inputpar);
    dzlog_info("getNetworkPolicy start 44 num[%d]", num);
    char *psJson = NULL;
    char uid[80] = {0};
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = "";
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.zone = log.zone;
    bool isError = false;
    dzlog_info("getNetworkPolicy start 55 num:%d", num);
    log_res.code = 200;
    StructToJson_NETWORKLIST(&psJson, &log_res, num, inputpar);

    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.node);
    free(log.zone);
    free_s(psJson);
    free_s(inputpar);
    return 0;
}

void* service_start_stop_pthread(void* arg)
{
    SERVICE_THREAD_PARAMS* params = (SERVICE_THREAD_PARAMS*)arg;
	terminalServiceOnoff(params->pcJson,params->action);
    free(params->pcJson);
    free(params);

	sleep(1);
	char uuid[64] = { 0 };
	GF_GetGUID(uuid);
	dzlog_info("terminalserviceEvent start");
	int ret = terminalserviceEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1); // 系统运行数据上报
	dzlog_info("terminalserviceEvent end");
	return NULL;
}

int retryExecutePolicyCmd(char *cmd,char *result)
{
    int cmd_ret = -1;    // 命令执行结果
    int retry = 0;       // 重试计数器
    dzlog_info("executing cmd: %s", cmd);
    // 最多重试3次
    while (retry < 3)
    {
        cmd_ret = popenCmd(cmd, result);
        // 检查命令执行结果（成功标识：ret=0 且结果包含"successfully"）
        if (cmd_ret == 0 && strlen(result) > 0 && !strstr(result, "successfully")==NULL)
        {
            dzlog_info("cmd success: %s", result);
            break;
        }
        dzlog_warn(" cmd: %s: retry(%d): %s", retry+1, cmd,result);
        retry++;
        usleep(100000); // 100ms延迟 
    }
    return retry;
}

int ExecutePolicyCmd(int type,int ssh,int mqtt,POLICY_PORT_PARAM* portList,char *result)
{
    dzlog_info("ExecutePolicyCmd");
    int ret =0;
    int count = 0;
    char cmd[64] = {0};  // 存储命令字符串
    if(type==1)
    {
        if (mqtt>0)
        {
            sprintf(cmd, "policy_ctrl enable mqtt-ex");
            count = retryExecutePolicyCmd(cmd, result);
        }
        else if (mqtt==0)
        {
            sprintf(cmd, "policy_ctrl disable mqtt-ex");
            count = retryExecutePolicyCmd(cmd, result);
        }
    }
    if(type==2)
    {
        if (ssh>0)
        {
            sprintf(cmd, "policy_ctrl start ssh --persist");
            count = retryExecutePolicyCmd(cmd, result);
        }
        else if (ssh==0)
        {
            sprintf(cmd, "policy_ctrl stop ssh --persist");
            count = retryExecutePolicyCmd(cmd, result);
        }
    }
    if(type==3)
    {
        if (portList == NULL)
        {
            dzlog_error("portList is NULL");
            return count;
        }
        int i = 0;
        // 遍历端口列表（假设portList以port=0作为结束标志，或根据实际长度遍历）
        while( i < 100) // 限制最大100个端口，防止越界
        {
            POLICY_PORT_PARAM *portParam = &portList[i];
            if(portParam->port==0)
            {
                dzlog_info("portList <= 0");
                break;
            }
            // 根据status执行不同操作
            switch (portParam->status)
            {
                case 0:  // status=0：跳过 不更改
                    dzlog_info("port %d status=0, skip", portParam->port);
                    break;

                case 1:  // status=1：启用/禁用（根据time）
                    if (portParam->time > 0)
                    {
                        sprintf(cmd, "policy_ctrl enable port --port=%d", portParam->port);
                    }
                    else if (portParam->time == 0)
                    {
                        sprintf(cmd, "policy_ctrl disable port --port=%d", portParam->port);
                    }
                    else
                    {
                        dzlog_error("port %d invalid time: %d", portParam->port, portParam->time);
                        break;
                    }
                    count = retryExecutePolicyCmd(cmd,result);
                    break;
                case 2:  // status=2：删除端口
                    sprintf(cmd, "policy_ctrl delete port --port=%d", portParam->port);
                    count = retryExecutePolicyCmd(cmd,result);
                    break;
                default:  // 未知status
                    dzlog_error("port %d invalid status: %d", portParam->port, portParam->status);
                    break;
            }
            i++;
            continue;
        }
    }
    return count;
}

void JsonToStruct_policySecurity(cJSON *json,ST_IOTA_LOG *pcStatusDecs)
{
    dzlog_info("JsonToStruct_policySecurity");
    cJSON *param = NULL;
    pcStatusDecs->iMid = strdup(cJSON_GetObjectItem(json, "mid")->valuestring);
    pcStatusDecs->deviceSn = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
    pcStatusDecs->zone = strdup(cJSON_GetObjectItem(json, "zone")->valuestring);
    pcStatusDecs->node = strdup(cJSON_GetObjectItem(json, "node")->valuestring);
    pcStatusDecs->msgTime = strdup(cJSON_GetObjectItem(json, "msgTime")->valuestring);
    pcStatusDecs->deviceID = strdup(cJSON_GetObjectItem(json, "deviceSn")->valuestring);
    if (cJSON_HasObjectItem(json, "params"))
    {
        param = cJSON_GetObjectItem(json, "params");
        POLICY_SECURITY_PARAM *st_param = pcStatusDecs->param;

        if (cJSON_HasObjectItem(param, "type"))
        {
            cJSON* typeItem = cJSON_GetObjectItem(param, "type"); 
            if (cJSON_IsNumber(typeItem))
            {
                st_param->type = typeItem->valueint;
            }
        }        

        if (cJSON_HasObjectItem(param, "forwardDev"))
        {
            strncpy(st_param->forwardDev, cJSON_GetObjectItem(param, "forwardDev")->valuestring, sizeof(st_param->forwardDev));
        }
        if (cJSON_HasObjectItem(param, "ipType"))
        {
           strncpy(st_param->ipType, cJSON_GetObjectItem(param, "ipType")->valuestring, sizeof(st_param->ipType));
        }

        if (cJSON_HasObjectItem(param, "videoPlatformIp"))
        {
            strncpy(st_param->videoPlatformIp, cJSON_GetObjectItem(param, "videoPlatformIp")->valuestring, sizeof(st_param->videoPlatformIp));
        }

        if (cJSON_HasObjectItem(param, "forwardStatus"))
        {
            strncpy(st_param->forwardStatus, cJSON_GetObjectItem(param, "forwardStatus")->valuestring, sizeof(st_param->forwardStatus));
        }

        if (cJSON_HasObjectItem(param, "videoPlatformMasklen"))
        {
            strncpy(st_param->videoPlatformMasklen, cJSON_GetObjectItem(param, "videoPlatformMasklen")->valuestring, sizeof(st_param->videoPlatformMasklen));
        }

        if (cJSON_HasObjectItem(param, "videoGateway"))
        {
            strncpy(st_param->videoGateway, cJSON_GetObjectItem(param, "videoGateway")->valuestring, sizeof(st_param->videoGateway));
        }

        if (cJSON_HasObjectItem(param, "portList"))
        {
            cJSON* portListArray = cJSON_GetObjectItem(param, "portList");
            if (cJSON_IsArray(portListArray))  // 确保是JSON数组类型
            {
                int arraySize = cJSON_GetArraySize(portListArray);
                // int maxPorts = sizeof(st_param->portList) / sizeof(st_param->portList[0]);  // 获取portList数组最大容量
                int i;
                
                // 遍历数组元素（限制不超过portList最大容量）
                for (i = 0; i < arraySize && i < 100; i++)
                {
                    cJSON* portObj = cJSON_GetArrayItem(portListArray, i);  // 获取数组中的单个对象
                    if (cJSON_IsObject(portObj))  // 确保数组元素是对象
                    {
                        // 解析port字段（如8080）
                        cJSON* portItem = cJSON_GetObjectItem(portObj, "port");
                        if (cJSON_IsNumber(portItem))
                        {
                            st_param->portList[i].port = portItem->valueint;
                        }
                        
                        // 解析time字段（如22）
                        cJSON* timeItem = cJSON_GetObjectItem(portObj, "time");
                        if (cJSON_IsNumber(timeItem))
                        {
                            st_param->portList[i].time = timeItem->valueint;
                        }
                        
                        cJSON* statusItem = cJSON_GetObjectItem(portObj, "status");
                        if (cJSON_IsNumber(statusItem))
                        {
                            st_param->portList[i].status =statusItem->valueint;
                        }
                        
                        dzlog_info("解析端口配置: port=%d, time=%d, status=%d",
                                  st_param->portList[i].port,
                                  st_param->portList[i].time,
                                  st_param->portList[i].status);
                    }
                }
            }
        }  
         
        if (cJSON_HasObjectItem(param, "ssh"))
        {
            cJSON* sshItem = cJSON_GetObjectItem(param, "ssh"); 
            if (cJSON_IsNumber(sshItem))
            {
                st_param->ssh = sshItem->valueint;
            }
        }  
        if (cJSON_HasObjectItem(param, "mqtt"))
        {
            cJSON* mqttItem = cJSON_GetObjectItem(param, "mqtt"); 
            if (cJSON_IsNumber(mqttItem))
            {
                st_param->mqtt = mqttItem->valueint;
            }
        }      
    }
}

int ParamToFilejson(POLICY_SECURITY_PARAM param,cJSON *in_json)
{

    // 添加SshServer和MqttPort字段（对应ssh和mqtt）
    char ssh[10] = {0};
    char mqtt[10] = {0};
    sprintf(ssh, "%d", param.ssh);
    sprintf(mqtt, "%d", param.mqtt);
    cJSON_AddStringToObject(in_json, "SshServer", ssh);
    cJSON_AddStringToObject(in_json, "MqttPort", mqtt);
    cJSON *jsonPort = cJSON_CreateObject();
    if (!jsonPort) {
        dzlog_error("Failed to create port JSON object");
        return -1;
    }
    char port[10] = {0};
    char time[10] = {0};
    // 遍历端口列表
    for (int i = 0; i < 100; i++) {  // 限制最大100个端口
        
        POLICY_PORT_PARAM *portParam = &param.portList[i];
        // dzlog_info("ParamToFilejson111:%d",portParam->port);
        if (portParam->port == 0) break;  // 遇到port=0表示结束
        
        // 跳过status=2的条目
        if (portParam->status == 2) continue;
        sprintf(port, "%d", portParam->port);
        sprintf(time, "%d", portParam->time);
        cJSON_AddStringToObject(jsonPort, port, time);

    }
    cJSON_AddItemToObject(in_json, "Port", jsonPort);
    return 0;
}

int setPolicySecurity(char *pcJson)
{
    dzlog_info("setPolicySecurity");
    cJSON *json = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        ST_IOTA_LOG log;
        POLICY_SECURITY_PARAM param;
        memset(&param, 0, sizeof(POLICY_SECURITY_PARAM)); 
        log.param = &param;
        JsonToStruct_policySecurity(json, &log);

        char *psJson;
        char uid[80] = {0};
        GF_GetGUID(uid);
        ST_IOTA_LOG_RES log_res;
        log_res.body = "";
        log_res.deviceID = log.deviceID;
        log_res.deviceSn = log.deviceSn;
        log_res.iMid = uid;
        log_res.node = log.node;
        log_res.replyId = log.iMid;
        log_res.zone = log.zone;
        log_res.requestID = NULL;
        bool isError = false;
        char result[256] = {0}; 
        dzlog_info("setPolicySecurity2");

        //提前将传入的json转为写入的json
        cJSON *in_json = cJSON_CreateObject();
        if (!in_json) {
            dzlog_error("Failed to create JSON object");
            isError = true;
            log_res.code = 500;
            goto Uerror;
        }
        int ret = ParamToFilejson(param,in_json);
        if(ret!=0){
            dzlog_error("ParamToFilejson error");
            isError = true;
            log_res.code = 500;
            goto Uerror;
        }
        dzlog_info("setPolicySecurity3");
        //修改文件 对文件加锁
        const char *filename = "/userdata/tmp/param.json";
        FILE *fp = fopen(filename, "w");
        if (fp == NULL && errno == ENOENT) {
            // 提取目录路径
            char dir_path[256];
            strncpy(dir_path, filename, sizeof(dir_path) - 1);
            char *last_slash = strrchr(dir_path, '/');
            if (last_slash != NULL) {
                *last_slash = '\0'; // 截断到目录部分
                // 创建目录(递归创建)
                char cmd[300];
                snprintf(cmd, sizeof(cmd), "mkdir -p %s", dir_path);
                system(cmd);
                // 再次尝试打开文件
                fp = fopen(filename, "w");
            }
        }
        if (fp == NULL) {
            isError=true;
            dzlog_error("Failed to open file: %s", strerror(errno));
            log_res.code = 500;
            goto Uerror;   
        }
        // 加排他锁（阻塞模式，等待其他进程释放锁）- 新增重试逻辑
        int retry_count = 0;
        int lock_result = -1;
        while (retry_count < 3 && lock_result != 0) {
            lock_result = flock(fileno(fp), LOCK_EX);
            if (lock_result == -1) {
                dzlog_warn("Failed to lock file (attempt %d): %s", retry_count + 1, strerror(errno));
                retry_count++;
                usleep(500000); // 500ms延迟
            }
        }
        if (lock_result == -1) {  // 三次重试后仍失败
            isError = true;
            dzlog_error("Failed to lock file after 3 attempts: %s", strerror(errno));
            log_res.code = 500;
            fclose(fp);
            goto Uerror;
        }
        dzlog_info("setPolicySecurity4");
        //加锁成功后，执行命令 重试3次
        retry_count = 0;
        retry_count = ExecutePolicyCmd(param.type,param.ssh,param.mqtt,param.portList,result);
        if(retry_count>=3)
        {
            dzlog_error("PolicyCmd error :%s,%s",ret,result);
            // 命令失败，释放锁并关闭文件
            flock(fileno(fp), LOCK_UN);
            fclose(fp);
            isError = true;
            log_res.code = 500;
            goto Uerror;    
        }

        // 写入 JSON 数据
        char *json_str = cJSON_Print(in_json);
        if (json_str) {
            fputs(json_str, fp);
            free(json_str);
        }
        // 释放锁并关闭文件
        flock(fileno(fp), LOCK_UN);
        fclose(fp);
       
        log_res.code = 200;
        StructToJson_PolicySecurity_Info(&psJson, &log_res,NULL);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    Uerror:
        if (isError)
        {
            StructToJson_PolicySecurity_Info(&psJson, &log_res,NULL);
            IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        }

    Ufree:
        cJSON_Delete(in_json);
        cJSON_Delete(json);
        free_s(log.iMid);
        free_s(log.deviceSn);
        free_s(log.deviceID);
        free_s(log.msgTime);
        free_s(log.node);
        free_s(log.zone);
        free_s(psJson);
        return 0; 
    }
}

int getPolicySecurity(char *pcJson)
{
    dzlog_info("getPolicySecurity");
    cJSON *json = NULL;
    cJSON* info_json=NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        ST_IOTA_LOG log;
        JsonToStruct_policySecurity(json, &log);

        char *psJson;
        char uid[80] = {0};
        GF_GetGUID(uid);
        ST_IOTA_LOG_RES log_res;
        log_res.body = "";
        log_res.deviceID = log.deviceID;
        log_res.deviceSn = log.deviceSn;
        log_res.iMid = uid;
        log_res.node = log.node;
        log_res.replyId = log.iMid;
        log_res.zone = log.zone;
        log_res.requestID = NULL;
        bool isError = false;
        int ret = 0;
        char *json_str = NULL;
        
        const char* filename = "/userdata/tmp/param.json";
        FILE* fp = fopen(filename, "rb");
        if (fp == NULL) {
            dzlog_info("Failed to open file");
            //如果文件不存在，则用命令获取
            // 获取 mqtt-ex 状态
            char mqtt_result[128] = {0};
            ret = popenCmd("policy_ctrl status mqtt-ex", mqtt_result);
            if (ret != 0 || strstr(mqtt_result, "successfully")==NULL) {
                dzlog_error("Error getting mqtt-ex status1");
                isError = true;
                log_res.code = 500;
                goto Uerror;        
            }

            // 获取 ssh 状态
            char ssh_result[128] = {0};
            ret = popenCmd("policy_ctrl status ssh", ssh_result);
            if (ret != 0 || strstr(ssh_result, "successfully")==NULL) {
                dzlog_error("Error getting ssh status1");
                isError = true;
                log_res.code = 500;
                goto Uerror;        
            }
            // 解析 mqtt-ex 状态 (enable/disable)
            char mqtt_port[5] = "-1";
            if (strstr(mqtt_result, "enable")!=NULL) {
                strcpy(mqtt_port, "255");
            } else if (strstr(mqtt_result, "disable")!=NULL) {
                strcpy(mqtt_port, "0");
            }else
            {
                dzlog_error("Error getting mqtt status2");
                isError = true;
                log_res.code = 500;
                goto Uerror;                    
            }
            // 解析 ssh 状态 (enable/disable)
            char ssh_server[5] = "-1";
            if (strstr(ssh_result, "enable")!=NULL) {
                strcpy(ssh_server, "255");
            } else if (strstr(ssh_result, "disable")!=NULL) {
                strcpy(ssh_server, "0");
            }else
            {
                dzlog_error("Error getting ssh status2");
                isError = true;
                log_res.code = 500;
                goto Uerror;                    
            }
            info_json = cJSON_CreateObject();
            cJSON_AddStringToObject(info_json, "SshServer", ssh_server);
            cJSON_AddStringToObject(info_json, "MqttPort", mqtt_port);
        }else
        {
            dzlog_info("open file");
            fseek(fp, 0, SEEK_END);
            long len = ftell(fp);
            fseek(fp, 0, SEEK_SET);

            if (len == 0) {
                fclose(fp);
                dzlog_info(" file is null");
                log_res.code = 200;//文件数据为空，但是正常情况
                goto Uerror;   
            }
            char* json_str = malloc(len + 1);
            fread(json_str, 1, len, fp);
            fclose(fp);
            json_str[len] = '\0';
            // dzlog_info("open file:%s",json_str);
            info_json = cJSON_Parse(json_str);
            free_s(json_str); 
            if (!info_json) {
                isError=true;
                dzlog_error("Failed cJSON_Parse");
                log_res.code = 500;
                goto Uerror;   
            }
        } 

        log_res.code = 200;
        StructToJson_PolicySecurity_Info(&psJson, &log_res,info_json);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    Uerror:
        if (isError)
        {
            StructToJson_PolicySecurity_Info(&psJson, &log_res,NULL);
            IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        }

    Ufree:
        free_s(log.iMid);
        free_s(log.deviceSn);
        free_s(log.deviceID);
        free_s(log.msgTime);
        free_s(log.node);
        free_s(log.zone);
        free_s(psJson);
        cJSON_Delete(info_json);
        cJSON_Delete(json);
        return 0; 
    }
    return -1; 
}

int setPolicySecurityVideo(char *pcJson)
{
    cJSON *json = NULL;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        ST_IOTA_LOG log;
        POLICY_SECURITY_PARAM param;
        log.param = &param;
        JsonToStruct_policySecurity(json, &log);


        char *psJson;
        char uid[80] = {0};
        GF_GetGUID(uid);
        ST_IOTA_LOG_RES log_res;
        log_res.body = "";
        log_res.deviceID = log.deviceID;
        log_res.deviceSn = log.deviceSn;
        log_res.iMid = uid;
        log_res.node = log.node;
        log_res.replyId = log.iMid;
        log_res.zone = log.zone;
        log_res.requestID = NULL;
        bool isError = false;

        const char* filename = "/userdata/tmp/video.json";
        // 创建根JSON对象
        cJSON *root = cJSON_CreateObject();

        // 添加键值对
        cJSON_AddStringToObject(root, "forward_status", param.forwardStatus);
        cJSON_AddStringToObject(root, "forward_dev", param.forwardDev);
        cJSON_AddStringToObject(root, "ip_type", param.ipType);
        cJSON_AddStringToObject(root, "video_platform_ip", param.videoPlatformIp);
        cJSON_AddStringToObject(root, "video_platform_masklen", param.videoPlatformMasklen);
        cJSON_AddStringToObject(root, "video_gateway", param.videoGateway);

        // 生成JSON字符串
        char *json_str = cJSON_Print(root);
        // 写入文件
        FILE *fp = fopen(filename, "w");
        if (fp == NULL && errno == ENOENT) {
            // 提取目录路径
            char dir_path[256];
            strncpy(dir_path, filename, sizeof(dir_path) - 1);
            char *last_slash = strrchr(dir_path, '/');
            if (last_slash != NULL) {
                *last_slash = '\0'; // 截断到目录部分
                // 创建目录(递归创建)
                char cmd[300];
                snprintf(cmd, sizeof(cmd), "mkdir -p %s", dir_path);
                system(cmd);
                // 再次尝试打开文件
                fp = fopen(filename, "w");
            }
        }
        if (fp == NULL) {
            isError=true;
            dzlog_error("Failed to open file: %s", strerror(errno));
            log_res.code = 500;
            goto Uerror;   
        }
        
        fputs(json_str, fp);
        fclose(fp);
        log_res.code = 200;
        StructToJson_policy_video_info(&psJson, &log_res,NULL);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    
    Uerror:
        if (isError)
        {
            StructToJson_policy_video_info(&psJson, &log_res,NULL);
            IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        }

    Ufree:
        cJSON_Delete(json);
        free_s(log.iMid);
        free_s(log.deviceSn);
        free_s(log.deviceID);
        free_s(log.msgTime);
        free_s(log.node);
        free_s(log.zone);
        free_s(psJson);
        free(json_str);
        cJSON_Delete(root);
        return 0; 
    }
}

int getPolicySecurityVideo(char *pcJson)
{
    dzlog_info("getPolicySecurityVideo");
    cJSON *json = NULL;
    char cmd[32] = {0};
    json = cJSON_Parse(pcJson);
    if (json)
    {
        ST_IOTA_LOG log;
        // POLICY_SECURITY_PARAM param;
        // log.param = &param;
        JsonToStruct_policySecurity(json, &log);
        
        char *psJson;
        char uid[80] = {0};
        GF_GetGUID(uid);
        ST_IOTA_LOG_RES log_res;
        log_res.body = "";
        log_res.deviceID = log.deviceID;
        log_res.deviceSn = log.deviceSn;
        log_res.iMid = uid;
        log_res.node = log.node;
        log_res.replyId = log.iMid;
        log_res.zone = log.zone;
        log_res.requestID = NULL;
        bool isError = false;

        const char* filename = "/userdata/tmp/video.json";
        FILE* fp = fopen(filename, "rb");
        if (fp == NULL) {
            isError=true;
            dzlog_info("Failed to open file");
            log_res.code = 200;//文件数据为空，但是正常情况
            goto Uerror;   
        }        
        fseek(fp, 0, SEEK_END);
        long len = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        if (len == 0) {
            fclose(fp);
            dzlog_info(" file is null");
            log_res.code = 200;//文件数据为空，但是正常情况
            goto Uerror;   
        }
        char* json_str = malloc(len + 1);
        fread(json_str, 1, len, fp);
        fclose(fp);
        json_str[len] = '\0';

        cJSON* video_json = cJSON_Parse(json_str);
        if (!video_json) {
            isError=true;
            dzlog_error("Failed cJSON_Parse");
            log_res.code = 500;
            goto Uerror;   
        }
        log_res.code = 200;
        StructToJson_policy_video_info(&psJson, &log_res,video_json);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        free(json_str);
        cJSON_Delete(video_json);
        

    Uerror:
        if (isError)
        {
            StructToJson_policy_video_info(&psJson, &log_res,NULL);
            IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        }

    Ufree:
        cJSON_Delete(json);
        free_s(log.iMid);
        free_s(log.deviceSn);
        free_s(log.deviceID);
        free_s(log.msgTime);
        free_s(log.node);
        free_s(log.zone);
        free_s(psJson);
        return 0; 
    }
}

/**
 * @brief 执行iptables命令并将结果读入字符串数组
 *
 * @param rules 用于存储规则的二维字符数组
 * @param max_rules 数组最大容量
 * @return int 读取到的规则数量，-1表示出错
 */
int read_iptables_rules(char rules[][512], int max_rules, char* filename) {
    // 执行iptables命令并输出到文件
    FILE* fp = NULL;
    int ret = -1;
    if (filename != NULL)
    {
        fp = fopen(filename, "r");
        if (!fp) {
            return -1;
        }
    }
    else
    {
        ret = system("iptables -S > ./iptables.txt");
        ret = system("cp ./iptables.txt ./iptables_b.txt");
        if (ret != 0) {
            return -1;
        }
        // 打开生成的规则文件
        fp = fopen("./iptables.txt", "r");
        if (!fp) {
            return -1;
        }
    }

    int count = 0;
    char buffer[512];

    // 逐行读取规则文件
    while (fgets(buffer, 512, fp) && count < max_rules) {
        // 移除行尾换行符
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        }

        // 复制到规则数组
        strncpy(rules[count], buffer, 512);
        count++;
    }
    fclose(fp);

    return count;
}

/**
 * @brief 解析单条iptables规则到结构体
 *
 * @param rule_line 单条iptables规则字符串
 * @param rule_struct 输出解析结果的结构体指针
 * @return int 0=成功, -1=失败(忽略该规则)
 */
int parse_iptables_rule(const char* tmp, IOTA_NETWORKLIST_PARAM_V2* rule_struct) {
    // 初始化结构体
    char rule_line[512] = { 0 };
    strncpy(rule_line, tmp, 512);

    memset(rule_struct, 0, sizeof(IOTA_NETWORKLIST_PARAM_V2));
    //rule_struct->srcPort = -1;  // -1表示未指定
    //rule_struct->dstPort = -1;  // -1表示未指定
    strncpy(rule_struct->srcIp, "0.0.0.0", sizeof(rule_struct->srcIp) - 1);
    strncpy(rule_struct->dstIp, "0.0.0.0", sizeof(rule_struct->dstIp) - 1);
    memset(rule_struct->state, 0, sizeof(rule_struct->state));   
    dzlog_info("parse_iptables_rule rule_line[%p][%s]", rule_line, rule_line);

    if (strstr(rule_line, "-o") != NULL)
    {
        return -1; // 忽略
    }
    strncpy(rule_struct->cmd, rule_line, 512);

    // 跳过规则动作(-A/-I)获取链名
    char* token = strtok((char*)rule_line, " ");
    if (!token || (strcmp(token, "-A") != 0 && strcmp(token, "-I") != 0)) {
        return -1; // 忽略非规则行
    }

    token = strtok(NULL, " ");
    if (!token) return -1;

    if (strcmp(token, "INPUT") != 0 && strcmp(token, "FORWARD") != 0 && strcmp(token, "OUTPUT") != 0)
    {
        //只接受系统规则链，即INPUT, FORWARD, OUTPUT
        return -1;
    }
    strncpy(rule_struct->chainDirection, token, sizeof(rule_struct->chainDirection) - 1);
    // 解析规则参数

    while ((token = strtok(NULL, " ")) != NULL) {
        // 匹配协议
        if (strcmp(token, "-p") == 0) {
            token = strtok(NULL, " ");
            if (token) {
                strncpy(rule_struct->protocol, token, sizeof(rule_struct->protocol) - 1);
            }
        }
        // 匹配 范围源IP
        else if (strcmp(token, "--src-range") == 0) {
            token = strtok(NULL, " ");
            if (token) {
                strncpy(rule_struct->srcIp, token, sizeof(rule_struct->srcIp) - 1);
            }
        }
        // 匹配 范围目标IP
        else if (strcmp(token, "--dst-range") == 0) {
            token = strtok(NULL, " ");
            if (token) {
                strncpy(rule_struct->dstIp, token, sizeof(rule_struct->dstIp) - 1);
            }
        }
        // 匹配源IP
        else if (strcmp(token, "-s") == 0) {
            token = strtok(NULL, " ");
            if (token) {
                char* pos;
                while ((pos = strstr(token, "/32")) != NULL) {
                    size_t tail_len = strlen(pos + 3) + 1;
                    memmove(pos, pos + 3, tail_len);
                }
                strncpy(rule_struct->srcIp, token, sizeof(rule_struct->srcIp) - 1);
            }
        }
        // 匹配目标IP
        else if (strcmp(token, "-d") == 0) {
            token = strtok(NULL, " ");
            if (token) {
                char* pos;
                while ((pos = strstr(token, "/32")) != NULL) {
                    size_t tail_len = strlen(pos + 3) + 1;
                    memmove(pos, pos + 3, tail_len);
                }
                strncpy(rule_struct->dstIp, token, sizeof(rule_struct->dstIp) - 1);
            }
        }
        // 匹配多源端口
        else if (strcmp(token, "--sports") == 0) {
            token = strtok(NULL, " ");
            if (token) strncpy(rule_struct->srcPort, token, sizeof(rule_struct->srcPort) - 1);
        }
        // 匹配源端口
        else if (strcmp(token, "--sport") == 0) {
            token = strtok(NULL, " ");
            if (token) strncpy(rule_struct->srcPort, token, sizeof(rule_struct->srcPort) - 1);
        }
        // 匹配多目标端口
        else if (strcmp(token, "--dports") == 0) {
            token = strtok(NULL, " ");
            if (token) strncpy(rule_struct->dstPort, token, sizeof(rule_struct->dstPort) - 1);
        }
        // 匹配目标端口
        else if (strcmp(token, "--dport") == 0) {
            token = strtok(NULL, " ");
            if (token) strncpy(rule_struct->dstPort, token, sizeof(rule_struct->dstPort) - 1);
        }
        // 匹配动作
        else if (strcmp(token, "-j") == 0) {
            token = strtok(NULL, " ");
            if (token)
            {
                if (strcmp(token, "ACCEPT") != 0 && strcmp(token, "DROP") != 0 && strcmp(token, "REJECT") != 0)
                {
                    //只接受系统规则链，即INPUT, FORWARD, OUTPUT
                    return -1;
                }
                strncpy(rule_struct->permissionStatus, token, sizeof(rule_struct->permissionStatus) - 1);
            }
        }
        // 匹配状态
        else if (strcmp(token, "--state") == 0) {      
            token = strtok(NULL, " ");
            if (token) {
                if (rule_struct->state[0] != '\0') strcat(rule_struct->state, ",");
                strncat(rule_struct->state, token, sizeof(rule_struct->state) - strlen(rule_struct->state) - 1);
            }
        }
        // 匹配ICMP类型
        else if (strcmp(token, "--icmp-type") == 0) {
            token = strtok(NULL, " ");
            if (token) {
                if (rule_struct->state[0] != '\0') strcat(rule_struct->state, ",");
                strcat(rule_struct->state, "icmp-type:");
                strncat(rule_struct->state, token, sizeof(rule_struct->state) - strlen(rule_struct->state) - 1);
            }
        }
        // 匹配模块
        else if (strcmp(token, "-m") == 0) {
            token = strtok(NULL, " ");
            // 记录模块名但暂不处理
        }
    }

    // 设置默认值
    if (rule_struct->permissionStatus[0] == '\0') {
        strcpy(rule_struct->permissionStatus, "ACCEPT");
    }

    // 处理未指定的协议
    if (rule_struct->protocol[0] == '\0') {
        strcpy(rule_struct->protocol, "all");
    }

    //// 处理ICMP协议的特殊情况
    //if (strcmp(rule_struct->protocol, "icmp") == 0 && rule_struct->state[0] == '\0') {
    //    strcpy(rule_struct->state, "any");
    //}

    return 0;
}

/**
 * @brief 解析iptables规则数组到结构体数组
 *
 * @param rules iptables规则字符串数组
 * @param rule_count 规则数量
 * @param parsed_rules 输出的结构体数组
 * @param max_parsed 最大解析数量
 * @return int 成功解析的规则数量
 */
int parse_iptables_rules(char rules[][512], int rule_count, IOTA_NETWORKLIST_PARAM_V2* parsed_rules, int max_parsed) {
    int parsed_count = 0;
    int i = 0;
    for (i = 0; i < rule_count && parsed_count < max_parsed; i++) {

        if (parse_iptables_rule(rules[i], &parsed_rules[parsed_count]) == 0) {

            parsed_count++;
        }
    }
    return parsed_count;
}

/**
 * @brief 向规则集合添加规则
 *
 * @param collection 规则集合指针
 * @param rule 要添加的规则
 */
void add_to_rule_collection(RuleCollection* collection, const IOTA_NETWORKLIST_PARAM_V2* rule) {
    // 如果空间不足，扩容
    if (collection->count >= collection->capacity) {
        int new_capacity = collection->capacity * 2;
        IOTA_NETWORKLIST_PARAM_V2* new_rules = realloc(collection->rules,
            new_capacity * sizeof(IOTA_NETWORKLIST_PARAM_V2));
        if (new_rules) {
            collection->rules = new_rules;
            collection->capacity = new_capacity;
        }
        else {
            perror("Failed to expand rule collection");
            return;
        }
    }

    // 添加规则
    collection->rules[collection->count] = *rule;
    collection->count++;
}

void classify_rules(IOTA_NETWORKLIST_PARAM_V2* parsed_rules, int rule_count,RuleCollection* input, RuleCollection* forward, RuleCollection* output) 
{
    int ii = 0;
    int jj = 0;
    int kk = 0;
    for (int i = 0; i < rule_count; i++) {
        if (strcmp(parsed_rules[i].chainDirection, "INPUT") == 0) {
            if (parsed_rules[i].ruleOrigin <= 0)
            {
                ii++;
                parsed_rules[i].ruleOrigin = ii;
            }
            add_to_rule_collection(input, &parsed_rules[i]);
        }
        else if (strcmp(parsed_rules[i].chainDirection, "FORWARD") == 0) {
            if (parsed_rules[i].ruleOrigin <= 0)
            {
                jj++;
                parsed_rules[i].ruleOrigin = jj;
            }
            add_to_rule_collection(forward, &parsed_rules[i]);
        }
        else if (strcmp(parsed_rules[i].chainDirection, "OUTPUT") == 0) {
            if (parsed_rules[i].ruleOrigin <= 0)
            {
                kk++;
                parsed_rules[i].ruleOrigin = kk;
            }
            add_to_rule_collection(output, &parsed_rules[i]);
        }
    }
}

void classify_rules_V1(IOTA_NETWORKLIST_PARAM_V2* parsed_rules, int rule_count, RuleCollection* ipt_entries)
{
    int ii = 0;
    int jj = 0;
    int kk = 0;
    for (int i = 0; i < rule_count; i++) {
        if (strcmp(parsed_rules[i].chainDirection, "INPUT") == 0) {
            if (parsed_rules[i].prio <= 0)
            {
                ii++;
                parsed_rules[i].prio = ii;
            }
        }
        else if (strcmp(parsed_rules[i].chainDirection, "FORWARD") == 0) {
            if (parsed_rules[i].prio <= 0)
            {
                jj++;
                parsed_rules[i].prio = jj;
            }
        }
        else if (strcmp(parsed_rules[i].chainDirection, "OUTPUT") == 0) {
            if (parsed_rules[i].prio <= 0)
            {
                kk++;
                parsed_rules[i].prio = kk;
            }
        }
        add_to_rule_collection(ipt_entries, &parsed_rules[i]);
    }
}

/**
 * @brief 初始化规则集合
 *
 * @param collection 规则集合指针
 * @param initial_capacity 初始容量
 */
void init_rule_collection(RuleCollection* collection, int initial_capacity) {
    collection->rules = malloc(initial_capacity * sizeof(IOTA_NETWORKLIST_PARAM_V2));
    memset(collection->rules,0, initial_capacity * sizeof(IOTA_NETWORKLIST_PARAM_V2));
    collection->count = 0;
    collection->capacity = initial_capacity;
}

/**
 * @brief 释放规则集合内存
 *
 * @param collection 规则集合指针
 */
void free_rule_collection(RuleCollection* collection) {
    dzlog_info("free_rule_collection count[%d]", collection->count);
    if (collection->rules) {
        free_s(collection->rules);
        collection->rules = NULL;
    }
    collection->count = 0;
    collection->capacity = 0;
}

// 打印规则集合的辅助函数
void print_rule_collection(const char* name, const RuleCollection* collection) {
    printf("\n===== %s Rules (%d) =====\n", name, collection->count);
    dzlog_info("\n===== %s Rules (%d) (%p) =====\n", name, collection->count, collection->rules);
    if (collection->count > collection->capacity)
    {
        return;
    }
    int i = 0;
    for (i = 0; i < collection->count; i++) {
        const IOTA_NETWORKLIST_PARAM_V2* rule = &collection->rules[i];
        
        dzlog_info("Rule #%d: %s %s %s", i + 1, rule->chainDirection, rule->permissionStatus, rule->protocol);
        dzlog_info("Rule id #%s", rule->policyId);
        dzlog_info("  Src: %-15s:%s", rule->srcIp, rule->srcPort);
        dzlog_info("  Dst: %-15s:%s", rule->dstIp, rule->dstPort);
        dzlog_info("  State: %s", rule->state);
        dzlog_info("  prio: %d", rule->prio);
    }
}

/**
 * @brief 比较两个规则是否相等（忽略id字段）
 *
 * @param rule1 第一个规则
 * @param rule2 第二个规则
 * @return true 规则内容相同
 * @return false 规则内容不同
 */
bool are_rules_equal(const IOTA_NETWORKLIST_PARAM_V2* rule1, const IOTA_NETWORKLIST_PARAM_V2* rule2) 
{
    bool ret = false;
    if (strcmp(rule1->chainDirection, rule2->chainDirection) == 0 &&
        strcmp(rule1->permissionStatus, rule2->permissionStatus) == 0 &&
        strcmp(rule1->protocol, rule2->protocol) == 0 &&
        strcmp(rule1->srcIp, rule2->srcIp) == 0 &&
        strcmp(rule1->dstIp, rule2->dstIp) == 0
        )
    {
        ret = true;
        if (rule1->state != NULL && strlen(rule1->state) != 0)
        {
            if (rule2->state != NULL && strlen(rule2->state) != 0)
            {
                if (strcmp(rule1->state, rule2->state) == 0)
                {
                    ret = true;
                }
            }
        }

        if (rule1->srcPort != NULL && strlen(rule1->srcPort) >0)
        {
            if (rule2->srcPort != NULL && strlen(rule2->srcPort) > 0)
            {
                if (strcmp(rule1->srcPort, rule2->srcPort) == 0)
                {
                    ret = true;
                }
                else
                {
                    ret = false;
                }
            }
            else
            {
                ret = false;
            }
        }
        else
        {
            if (rule2->srcPort != NULL && strlen(rule2->srcPort) > 0)
            {
                ret = false;
            }
            else
            {
                ret = true;
            }
        }


        if (rule1->dstPort != NULL && strlen(rule1->dstPort) > 0)
        {
            if (rule2->srcPort != NULL && strlen(rule2->dstPort) > 0)
            {
                if (strcmp(rule1->dstPort, rule2->dstPort) == 0)
                {
                    ret = true;
                }
                else
                {
                    ret = false;
                }
            }
            else
            {
                ret = false;
            }
        }
        else
        {
            if (rule2->dstPort != NULL && strlen(rule2->dstPort) > 0)
            {
                ret = false;
            }
            else
            {
                ret = true;
            }
        }
    }
    else
    {
        //dzlog_info("不一致 rule1->srcIp[%s],rule2->srcIp[%s],rule1->dstIp[%s],rule2->dstIp[%s]", rule1->srcIp, rule2->srcIp, rule1->dstIp, rule2->dstIp);
        ret = false;
    }
    return ret;
}

/**
 * @brief 在规则集合中查找规则
 *
 * @param collection 规则集合（系统iptables）
 * @param rule 要查找的规则  （库表iptables）
 * @return int 规则索引（找到）或 -1（未找到）
 */
int find_rule_in_collection(const RuleCollection* collection,IOTA_NETWORKLIST_PARAM_V2* rule,int flag) {
    for (int i = 0; i < collection->count; i++) {
        if (collection->rules[i].already_matched == 1) { continue; }//已经匹配过的数据，跳过
        //dzlog_info("find_rule_in_collection rules.dstIp[%s],rules.prio[%d],rule.dstIp[%s],rule.prio[%d],", collection->rules[i].dstIp, collection->rules[i].prio, rule->dstIp, rule->prio);
        if (are_rules_equal(&collection->rules[i], rule)) {
            collection->rules[i].already_matched = 1;
            if (flag == 1)
            {
                rule->prio = collection->rules[i].prio;
            }
            return i;
        }
    }
    return -1;
}

/**
 * @brief 对比并更新规则集合
 *
 * @param input_rules 新规则集合（系统当前规则）
 * @param db_input_rules 待更新的数据库规则集合（将被修改）
 * @return int 更新的规则数量（添加+删除）
 */
int update_rule_collection(const RuleCollection* input_rules, RuleCollection* db_input_rules) 
{
    // 1. 找出需要删除的规则（在db中有但在系统中不存在）
    int* to_remove = malloc(db_input_rules->count * sizeof(int));
    int remove_count = 0;

    for (int i = 0; i < db_input_rules->count; i++) {
        //dzlog_info("update_rule_collection i[%d]", i);
        if (find_rule_in_collection(input_rules, &db_input_rules->rules[i],1) == -1) {
            to_remove[remove_count++] = i;
            dzlog_info("update_rule_collection need to delete i[%d],prio[%d]",i, db_input_rules->rules[i].prio);
            
            //删除表记录
            SqlDeleteNetworkFirewallById(db_input_rules->rules[i].policyId);
        }
    }
    // 2. 找出需要添加的规则（在系统中存在但在db中不存在）
    int* to_add = malloc(input_rules->count * sizeof(int));
    int add_count = 0;

    for (int i = 0; i < input_rules->count; i++) 
    {
        if (find_rule_in_collection(db_input_rules, &input_rules->rules[i],0) == -1) {
            to_add[add_count++] = i;
        }
    }
    // 3. 执行删除操作（从后向前删除以避免索引变化问题）
    for (int i = remove_count - 1; i >= 0; i--) {
        int idx = to_remove[i];
        int j = 0;
        // 从集合中移除规则（移动后续元素）
        for (j = idx; j < db_input_rules->count - 1; j++) {
            db_input_rules->rules[j] = db_input_rules->rules[j + 1];
        }
        db_input_rules->count--;
    }
    // 4. 执行添加操作
    // 确保有足够容量
    if (db_input_rules->count + add_count > db_input_rules->capacity) {
        int new_capacity = db_input_rules->capacity + add_count + 10;
        IOTA_NETWORKLIST_PARAM_V2* new_rules = realloc(
            db_input_rules->rules,
            new_capacity * sizeof(IOTA_NETWORKLIST_PARAM_V2));

        if (new_rules) {
            db_input_rules->rules = new_rules;
            db_input_rules->capacity = new_capacity;
        }
        else {
            // 内存分配失败，回滚
            free(to_remove);
            free(to_add);
            return -1;
        }
    }
    // 添加新规则
    for (int i = 0; i < add_count; i++) {
        int idx = to_add[i];
        db_input_rules->rules[db_input_rules->count] = input_rules->rules[idx];
        char snowflakeId[32] = { 0 };
        getSnowflakeId(snowflakeId);
        //在这里设置id和来源字段
        sprintf(db_input_rules->rules[db_input_rules->count].policyId, "%s", snowflakeId);
        db_input_rules->rules[db_input_rules->count].ruleOrigin = 1;
        db_input_rules->count++;
    }
    // 清理临时数组
    free(to_remove);
    free(to_add);

    return remove_count + add_count;
}

int sync_iptables_rules_to_db(RuleCollection* db_ipt_entries)
{
    char iptables_rules[50][512];
    int rule_count = 0;
    //1.读取系统iptables规则
    if ((rule_count = read_iptables_rules(iptables_rules, 50,NULL)) < 0) {
        fprintf(stderr, "Error reading iptables rules\n");
        return 1;
    }
    //1.1系统iptables内容拆分成字段
    IOTA_NETWORKLIST_PARAM_V2 parsed_rules[50] = {0};
    int parsed_count = parse_iptables_rules(iptables_rules, rule_count, parsed_rules, 50);
    //1.2初始化并分类规则集合
    RuleCollection ipt_entries;
    init_rule_collection(&ipt_entries, 50);
    RuleCollection db_ipt_entries_tmp;
    init_rule_collection(&db_ipt_entries_tmp, 50);
    //1.2.1从总集合中并设置优先级字段
    classify_rules_V1(parsed_rules, parsed_count, &ipt_entries);
    dzlog_info("sync_iptables_rules_to_db parsed_count[%d]", parsed_count);
    print_rule_collection("xitong", &ipt_entries);
    //2读取数据库表
    PIOTA_NETWORKLIST_PARAM_V2 db_rules = (PIOTA_NETWORKLIST_PARAM_V2)malloc(sizeof(IOTA_NETWORKLIST_PARAM_V2) * (50));
    memset(db_rules,0, sizeof(IOTA_NETWORKLIST_PARAM_V2) * (50));
    int num = SqlSearNetworkPolicy_V2(db_rules);
    //2.1分类规则并设置优先级字段
    classify_rules_V1(db_rules, num, &db_ipt_entries_tmp);
    print_rule_collection("db", &db_ipt_entries_tmp);
    //3对比,更新
    int changes = update_rule_collection(&ipt_entries, &db_ipt_entries_tmp);
    classify_rules_V1(db_ipt_entries_tmp.rules, db_ipt_entries_tmp.count, db_ipt_entries);//再次更新优先级字段
    //4.插表
    int remsg = SqlINSERTIntoNetworkFirewall(db_ipt_entries);//插表,并以主键进行冲突覆盖
    //5.释放缓存
    free_s(db_rules);
    free_rule_collection(&ipt_entries);
    free_rule_collection(&db_ipt_entries_tmp);
    
    return 0;
}

char* replace_A_with_D(const char* input) {
    // 分配输出缓冲区（与输入等大）
    char* output = malloc(strlen(input) + 1);
    if (!output) return NULL;

    char* out_ptr = output;
    const char* in_ptr = input;
    bool at_line_start = true;  // 标记行首位置

    while (*in_ptr) {
        // 检测行首的 "-A " 模式
        if (at_line_start &&
            in_ptr[0] == '-' &&
            in_ptr[1] == 'A' &&
            (in_ptr[2] == ' ' || in_ptr[2] == '\t')) {

            // 替换为 "-D"
            *out_ptr++ = '-';
            *out_ptr++ = 'D';
            in_ptr += 2;  // 跳过已处理的 "A"
            at_line_start = false;
            continue;
        }

        // 复制当前字符
        *out_ptr++ = *in_ptr;

        // 更新行首状态（遇到换行符重置）
        at_line_start = (*in_ptr == '\n');
        in_ptr++;
    }

    *out_ptr = '\0';  // 终止字符串
    return output;
}

/// @brief 设置防火墙-新版接口-20250811版本
/// @param pJson
/// @param action 设置防火墙规则
/// @return
int firewallOps(char* pcJson)
{
    dzlog_info("firewallOps start");
    int ret = -1;
    int i = 0;
    bool isError = false;
    char uid[37] = { 0 };
    char* psJson = NULL;
    char msg[64] = { 0 };
    int flag_init = -1;

    ST_IOTA_LOG log;
    IOTA_NETWORKLIST_PARAM_V2 param[2] = { 0 };
    log.param = &param;
    int num = JsonToStruct_ServiceFirewall_V3(pcJson, &log,1);

    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = NULL;
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.zone = log.zone;

    sprintf(msg, "执行中");
    log_res.code = 100;
    StructToJson_firewall(&psJson, &log_res, NULL, msg);
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    free_s(psJson);

    CommunicationMode mode = SINGLE_SOURCE_SINGLE_DEST;//默认
    int sport_mode = -1;
    int dport_mode = -1;
    //检查参数,标记何种场景 start
    for (i = 0; i < num; i++)
    {
        if (param[i].srcPort != NULL && strlen(param[i].srcPort) != 0)
        {
            if (strchr(param[i].srcPort, ',') != NULL)
            {
                sport_mode = 1;
            }
            else
            {
                sport_mode = 0;
            }
        }
        else
        {
            sport_mode = 0;
        }
        if (param[i].dstPort != NULL && strlen(param[i].dstPort) != 0)
        {
            if (strchr(param[i].dstPort, ',') != NULL)
            {
                dport_mode = 1;
            }
            else
            {
                dport_mode = 0;
            }
        }
        else
        {
            dport_mode = 0;
        }
        if (sport_mode == 1 && dport_mode == 1)
        {
            mode = MULTI_SOURCE_MULTI_DEST;
            sprintf(msg, "不支持多目标端口加多源端口的场景");
            log_res.code = 708;
            isError = true;
            goto Uerror;
        }
        else if (sport_mode == 0 && dport_mode == 1)
        {
            mode = SINGLE_SOURCE_MULTI_DEST;
        }
        else if (sport_mode == 1 && dport_mode == 0)
        {
            mode = MULTI_SOURCE_SINGLE_DEST;
        }

        if (strcmp(param[i].operation, "DELETE") != 0)
        {
            if (strcmp(param[i].srcIp, "0.0.0.0") == 0)
            {
                if (strcmp(param[i].dstIp, "0.0.0.0") == 0)
                {
                    if (strcmp(param[i].permissionStatus, "REJECT") == 0 || strcmp(param[i].permissionStatus, "DROP") == 0)
                    {
                        sprintf(msg, "不被允许的操作");
                        log_res.code = 705;
                        isError = true;
                        goto Uerror;
                    }
                }
                if (strcmp(param[i].permissionStatus, "DROP") == 0 && strcmp(param[i].dstPort, "35520") == 0 && strcmp(param[i].chainDirection, "INPUT") == 0)
                {
                    sprintf(msg, "不被允许的操作");
                    log_res.code = 705;
                    isError = true;
                    goto Uerror;
                }
            }
        }
    }
    //检查参数end
    
    //进行一次同步 start  防止从平台加策略，但从设备侧删除了，数据库内还会留存数据，导致失败码701
    dzlog_info("setNetworkPolicy lsc test 1");
    RuleCollection db_ipt_entries;
    init_rule_collection(&db_ipt_entries, 50);
    IOTA_NETWORKLIST_PARAM_V2* rules_tmp = db_ipt_entries.rules;
    ret = sync_iptables_rules_to_db(&db_ipt_entries);
    db_ipt_entries.rules = rules_tmp;
    free_rule_collection(&db_ipt_entries);
    dzlog_info("setNetworkPolicy lsc test 2");
    //进行一次同步 end

    for (i = 0; i < num; i++)
    {
        if (strncmp("ADD", param[i].operation, 3) == 0)
        {
            //增加一个查表动作，对比表已有数据，是否有相同的，有则不再增加
            int ii = 0;
            ii = SqlSearNetworkPolicyCOUNT_V2(&param[i]);
            dzlog_info("setNetworkPolicy start  ii[%d]", ii);
            if (ii <= 0)
            {
                ret = setFirewallRule_V2(param[i], param[i].operation, mode,0);
                if (ret >= 0)
                {
                    dzlog_info("setNetworkPolicy start  4");
                    log_res.code = 200;
                    int remsg = SqlINSERTIntoNetworkFirewallOne(&param[i]);//插表
                }
                else if (ret == -2)
                {
                    sprintf(msg, "该系统不支持连续IP范围的设置");
                    log_res.code = 707;
                    isError = true;
                    dzlog_error("iprange not supported");
                    goto Uerror;
                }
                else
                {
                    sprintf(msg, "执行指令失败，请检查参数");
                    log_res.code = 702;
                    isError = true;
                    dzlog_error("setNetworkPolicy set firewall");
                    goto Uerror;
                }
            }
            else
            {   
                sprintf(msg, "已有相同的策略");
                log_res.code = 701;
                isError = true;
                goto Uerror;
            }
            dzlog_info("setNetworkPolicy start  5");
        }
        else if (strncmp("DELETE", param[i].operation, 6) == 0)
        {
            dzlog_info("firewallOps start 11");
            // 先根据id查表，然后删策略，再删记录
            IOTA_NETWORKLIST_PARAM_V2 inputpar = { 0 };
            ret = SqlSearNetworkFirewallByid(&inputpar,param[i].policyId);
            dzlog_info("firewallOps start 22 ret[%d]", ret);
            if (ret < 0)
            {
                //找不到相关策略
                sprintf(msg, "找不到策略id");
                log_res.code = 704;
                isError = true;
                dzlog_info("firewallOps start 333 ret[%d]", ret);
                goto Uerror;
            }
            else
            { 
                if (inputpar.ruleOrigin == 1 || inputpar.ruleOrigin == 0)
                {
                    //这种情况下需要找到实际的完整规则
// 
                    //2.查询系统iptables规则表得到ipt_entries
                    char iptables_rules[50][512];
                    int rule_count = 0;
                    if ((rule_count = read_iptables_rules(iptables_rules, 50,NULL)) < 0) {
                        fprintf(stderr, "Error reading iptables rules\n");
                        //return 1;
                    }
                    IOTA_NETWORKLIST_PARAM_V2 parsed_rules[50] = { 0 };
                    int parsed_count = parse_iptables_rules(iptables_rules, rule_count, parsed_rules, 50);

                    RuleCollection ipt_entries;
                    init_rule_collection(&ipt_entries, 50);
                    classify_rules_V1(parsed_rules, parsed_count, &ipt_entries);
                    dzlog_info("firewallOps start 6");

                    //3.根据步骤1信息对比iptables规则，修改为新的优先级，得到新的iptables_new.txt
                    ret = find_rule_in_collection(&ipt_entries, &inputpar, 1);
                    
                    char* modified = replace_A_with_D(ipt_entries.rules[ret].cmd);
                    if (modified) 
                    {
                        printf("Modified rules:\n%s\n", modified);
                        dzlog_info("firewallOps start 61 modified[%s]", modified);

                        char cmd_tmp[256] = { 0 };
                        sprintf(cmd_tmp, "iptables ");
                        strcat(cmd_tmp, modified);
                        dzlog_info("firewallOps start 62 cmd_tmp[%s]", cmd_tmp);

                        FILE* fp = popen(cmd_tmp, "r");
                        if (fp == NULL)
                        {
                            dzlog_error("Failed to execute command setFirewallRule_V1");
                            return -1;
                        }
                        int ret = 0;
                        char buffer[1024];
                        while (fgets(buffer, sizeof(buffer), fp) != NULL)
                        {
                            ret = -1;
                            dzlog_info("commond:[%s]", buffer);
                            if (strlen(buffer) > 0)//发生错误
                            {
                                dzlog_info("commond error");
                            }
                        }
                        pclose(fp);

                        free(modified);
                    }

                }
                else
                {
                    if (setFirewallRule_V2(inputpar, param[i].operation, mode,0) >= 0)
                    {
                        log_res.code = 200;
                        int remsg = SqlDeleteNetworkFirewallById(param[i].policyId);//
                    }
                    else
                    {
                        dzlog_error("执行指令失败，请检查参数");
                        sprintf(msg, "执行指令失败，请检查参数");
                        log_res.code = 702;
                        isError = true;
                        goto Uerror;
                    }
                }
            }
        }
        else if (strncmp("UPDATE", param[i].operation, 6) == 0)
        {
            // 先查表，然后删策略，再删记录。再加，再插记录
            IOTA_NETWORKLIST_PARAM_V2 inputpar = { 0 };
            ret = SqlSearNetworkFirewallByid(&inputpar, param[i].policyId);
            if (ret < 0)
            {
                //找不到相关策略
                sprintf(msg, "找不到策略id");
                log_res.code = 704;
                isError = true;
                goto Uerror;
            }
            else
            {
                ret = setFirewallRule_V2(param[i], "ADD", mode, inputpar.prio);
                if (ret >= 0)
                {
                    log_res.code = 200;
                    // 往表插记录
                    int remsg = SqlINSERTIntoNetworkFirewallOne(&param[i]);//插表,并冲突覆盖
                }
                else if (ret == -2)
                {
                    sprintf(msg, "该系统不支持连续IP范围的设置");
                    log_res.code = 707;
                    isError = true;
                    dzlog_error("iprange not supported");
                    goto Uerror;
                }
                else
                {
                    sprintf(msg, "执行指令失败，请检查参数");
                    log_res.code = 702;
                    isError = true;
                    dzlog_error("setNetworkPolicy set firewall");
                    goto Uerror;
                }
                if (setFirewallRule_V2(inputpar, "DELETE", mode, 0) >= 0)
                {
                    log_res.code = 200;
                    // 往表插记录
                    //int remsg = SqlDeleteNetworkFirewallById(param[i].policyId);
                }
                else
                {
                    dzlog_error("执行指令失败，请检查参数");
                    sprintf(msg, "执行指令失败，请检查参数");
                    log_res.code = 702;
                    isError = true;
                    goto Uerror;
                }
            }
        }
        else
        {
            dzlog_error("setNetworkPolicy set firewall 7 operation[%s]", param[i].operation);
            sprintf(msg, "未定义的操作[%s]", param[i].operation);
            log_res.code = 703;
            isError = true;
            goto Uerror;
        }
    }
    dzlog_info("setNetworkPolicy start  6 isError[%d]", isError);


    //RuleCollection db_ipt_entries;
    init_rule_collection(&db_ipt_entries, 50);
    dzlog_info("setNetworkPolicy start  7 isError[%d]", isError);
    rules_tmp = db_ipt_entries.rules;
    flag_init = 1;
    ret = sync_iptables_rules_to_db(&db_ipt_entries);
    dzlog_info("sync_iptables_rules_to_db end  db_ipt_entries->count[%d]", db_ipt_entries.count);
    db_ipt_entries.rules = rules_tmp;



    if (!isError)
    {
        GF_GetGUID(uid);
        log_res.iMid = uid;
        log_res.code = 200;
        log_res.replyId = log.iMid;
        StructToJson_firewall(&psJson, &log_res, &db_ipt_entries,"执行成功");
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        char uuid[37] = { 0 };
        GF_GetGUID(uuid);
        int ret = terminalnetstatEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1);
    }
Uerror:
    if (isError)
    {
        GF_GetGUID(uid);
        log_res.iMid = uid;
        log_res.replyId = log.iMid;
        dzlog_info("sync_iptables_rules_to_db 1111");
        StructToJson_firewall(&psJson, &log_res,NULL, msg);
        dzlog_info("sync_iptables_rules_to_db 22");
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.node);
    free(log.zone);
    free_s(psJson);
    if (flag_init == 1)
    {
        db_ipt_entries.rules = rules_tmp;
        free_rule_collection(&db_ipt_entries);
    }

    return 0;
}

/// @brief 同步防火墙-新版接口-20250811版本
/// @param pJson
/// @param action 同步防火墙规则
/// @return
int uploadRuleset(char* pcJson)
{
    dzlog_info("uploadRuleset start");
    int ret = -1;
    ST_IOTA_LOG log = {0};
    dzlog_info("uploadRuleset start 0");
    int num = JsonToStruct_ServiceFirewall_V3(pcJson, &log,0);
    char* psJson = NULL;
    char uid[37] = { 0 };
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = NULL;
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.zone = log.zone;
    log_res.code = 100;
    StructToJson_firewall(&psJson, &log_res, NULL, "执行中");
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    free_s(psJson);
    bool isError = false;
    int i = 0;
    
    //调用同步，
    //设备系统的规则表—>缓存1->
    //数据库表->         缓存2->   对比缓存1、2->更新数据库表，返回更新后数据库表
    RuleCollection db_ipt_entries;
    init_rule_collection(&db_ipt_entries, 50);
    IOTA_NETWORKLIST_PARAM_V2* rules_tmp = db_ipt_entries.rules;
    ret = sync_iptables_rules_to_db(&db_ipt_entries);
    dzlog_info("sync_iptables_rules_to_db end  db_ipt_entries->count[%d]", db_ipt_entries.count);
    db_ipt_entries.rules = rules_tmp;
    if (!isError)
    {
        log_res.code = 200;
        StructToJson_firewall(&psJson, &log_res, &db_ipt_entries, "执行成功");
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        char uuid[37] = { 0 };
        GF_GetGUID(uuid);
        int ret = terminalnetstatEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1);
    }
Uerror:
    if (isError)
    {
        GF_GetGUID(uid);
        log_res.iMid = uid;
        log_res.code = 706;
        StructToJson_firewall(&psJson, &log_res, &db_ipt_entries, NULL);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.node);
    free(log.zone);
    free_s(psJson);
    db_ipt_entries.rules = rules_tmp;
    free_rule_collection(&db_ipt_entries);
    return 0;
}

// 移动行位置（行号从0开始计数）
void move_line(char rules[100][512], int total_lines, int from_idx, int to_idx) {

    // 检查索引有效性
    if (from_idx < 0 || from_idx >= total_lines ||
        to_idx < 0 || to_idx >= total_lines) {
        printf("错误: 行号超出范围 (1-%d)\n", total_lines);
        return;
    }

    if (from_idx == to_idx) {
        return; // 相同位置不需要移动
    }

    // 保存要移动的行
    char temp[512];
    strcpy(temp, rules[from_idx]);

    // 移动行位置
    if (from_idx > to_idx) {
        // 向上移动：从from_idx到to_idx+1的行向下移动
        for (int i = from_idx; i > to_idx; i--) {
            strcpy(rules[i], rules[i - 1]);
        }
    }
    else {
        // 向下移动：从from_idx+1到to_idx的行向上移动
        for (int i = from_idx; i < to_idx; i++) {
            strcpy(rules[i], rules[i + 1]);
        }
    }

    // 将移动的行放入新位置
    strcpy(rules[to_idx], temp);
}

/// @brief 防火墙新版接口-20250811版本
/// @param pJson
/// @param action 交换防火墙规则顺序
/// @return
int swapFirewall(char* pcJson)
{
    dzlog_info("swapFirewall start");
    int ret = -1;
    ST_IOTA_LOG log;
    IOTA_NETWORKLIST_PARAM_V3 param = { 0 };
    log.param = &param;
    int num = JsonToStruct_ServiceFirewall_V4(pcJson, &log);
    char* psJson = NULL;
    char uid[37] = { 0 };
    GF_GetGUID(uid);
    ST_IOTA_LOG_RES log_res;
    log_res.body = NULL;
    log_res.deviceID = log.deviceID;
    log_res.deviceSn = log.deviceSn;
    log_res.iMid = uid;
    log_res.node = log.node;
    log_res.replyId = log.iMid;
    log_res.zone = log.zone;
    char msg[32] = { 0 };
    int flag_init = -1;
    sprintf(msg, "执行中");

    log_res.code = 100;
    StructToJson_firewall(&psJson, &log_res, NULL, msg);
    IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    free_s(psJson);
    bool isError = false;

    //1.根据id查询策略完整信息得到db_itb
    IOTA_NETWORKLIST_PARAM_V2 db_itb = { 0 };

    ret = SqlSearNetworkFirewallByid(&db_itb, param.policyId);
    if (ret < 0)
    {
        //找不到相关策略
        sprintf(msg, "找不到策略id");
        log_res.code = 704;
        isError = true;
        goto Uerror;
    }

    if (strcmp(db_itb.srcIp, "0.0.0.0") == 0)
    {
        if (strcmp(db_itb.dstIp, "0.0.0.0") == 0)
        {
            if (strcmp(db_itb.permissionStatus, "REJECT") == 0 || strcmp(db_itb.permissionStatus, "DROP") == 0)
            {
                //找不到相关策略
                sprintf(msg, "不被允许的操作");
                log_res.code = 705;
                isError = true;
                goto Uerror;
            }
        }
    }

    //2.查询系统iptables规则表得到ipt_entries
    char iptables_rules[50][512];
    int rule_count = 0;
    if ((rule_count = read_iptables_rules(iptables_rules, 50,NULL)) < 0) {
        fprintf(stderr, "Error reading iptables rules\n");
        //return 1;
    }
    IOTA_NETWORKLIST_PARAM_V2 parsed_rules[50] = { 0 };
    int parsed_count = parse_iptables_rules(iptables_rules, rule_count, parsed_rules, 50);

   
    RuleCollection ipt_entries;
    init_rule_collection(&ipt_entries, 50);
    classify_rules_V1(parsed_rules, parsed_count, &ipt_entries);

    //3.根据步骤1信息对比iptables规则，修改为新的优先级，得到新的iptables_new.txt
    ret = find_rule_in_collection(&ipt_entries, &db_itb,1);
    if (ret == -1)
    {
        dzlog_info("swapFirewall start 8");
    }
    else
    {
        //知道，ret
        int ii = 0;
        int jj = 0;
        int isfind1 = -1;
        int isfind2 = -1;
        char flag_str[32] = { 0 };
        sprintf(flag_str, "-A %s", db_itb.chainDirection);
        
        for (ii = 0; ii < rule_count; ii++)
        {
            if (strcmp(ipt_entries.rules[ret].cmd, iptables_rules[ii]) == 0)
            {
                isfind1 = ii;
            }

            if (strstr(iptables_rules[ii], flag_str) != NULL)
            {
                jj++;
                if (param.newPrio == jj)
                {
                    isfind2 = ii;
                }
            }
            if (isfind1 != -1 && isfind2 != -1)
            {
                break;
            }
        }
        if (isfind1 != -1 && isfind2 != -1 && isfind1 != isfind2)
        {
            move_line(iptables_rules, rule_count, isfind1, isfind2);
        }
        else
        {
            //没找到
            dzlog_info("not found 没找到");
        }
        

    }
    int i = 0;
    
    //4.根据新的iptables_new.txt，覆写规则，如果失败则用备份iptables.txt还原
    FILE* file = fopen("./iptables_new.txt", "w");
    if (!file) {
        perror("创建文件失败");
        //return 0;
    }
    for (i = 0; i < rule_count; i++) {
        fprintf(file, "%s\n", iptables_rules[i]);
    }
    fclose(file);

    ///////////////////重写规则表/////////////////////////////////
    // 先清空现有规则
    system("iptables -F");
    // 逐条添加规则
    for (i = 0; i < rule_count; i++) 
    {
        if (strncmp(iptables_rules[i], "-A ", 3) == 0) {
            // 构造iptables命令
            char command[256] = {0};
            snprintf(command, sizeof(command), "iptables %s", iptables_rules[i]);

            // 执行命令
            if (system(command) != 0) {
                fprintf(stderr, "Failed to execute: %s", command);
            }
        }
    }
    //调用同步，
    //设备系统的规则表—>缓存1->
    //数据库表->         缓存2->   对比缓存1、2->更新数据库表，返回更新后数据库表
    RuleCollection db_ipt_entries;
    init_rule_collection(&db_ipt_entries, 100);
    IOTA_NETWORKLIST_PARAM_V2* rules_tmp = db_ipt_entries.rules;
    flag_init = 1;
    ret = sync_iptables_rules_to_db(&db_ipt_entries);
    db_ipt_entries.rules = rules_tmp;
    if (!isError)
    {
        GF_GetGUID(uid);
        log_res.iMid = uid;
        log_res.code = 200;
        StructToJson_firewall(&psJson, &log_res, &db_ipt_entries, "执行成功");
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
        char uuid[37] = { 0 };
        GF_GetGUID(uuid);
        int ret = terminalnetstatEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1);
    }
Uerror:
    if (isError)
    {
        GF_GetGUID(uid);
        log_res.iMid = uid;
        StructToJson_firewall(&psJson, &log_res, NULL, msg);
        IOTA_SendMqtt("/v1/devices/security/response", psJson, strlen(psJson));
    }

Ufree:
    free(log.iMid);
    free(log.deviceSn);
    free(log.deviceID);
    free(log.node);
    free(log.zone);
    free_s(psJson);

    if (flag_init == 1)
    {
        db_ipt_entries.rules = rules_tmp;
        free_rule_collection(&db_ipt_entries);
    }
    return 0;
}

int security_commond(char *pcJson)
{
    cJSON *json = NULL;
    char cmd[32] = {0};
    int ret = -1;
    json = cJSON_Parse(pcJson);
    if (json)
    {
        strncpy(cmd, cJSON_GetObjectItem(json, "cmd")->valuestring, sizeof(cmd));
        dzlog_info("security_commond cmd[%s] ", cmd);

        if (strstr(cmd, "killProcess"))
        {
            terminalServiceKill(pcJson);

            //由于实际业务执行耗时较长，且会影响setFullReport本身的响应，所以起线程执行业务
            pthread_t thread;
            pthread_attr_t attr;
            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

            pthread_create(&thread, &attr, update_process_status_pthread, NULL);
            pthread_attr_destroy(&attr);
        }
        else if (strstr(cmd, "startService"))
        {
            SERVICE_THREAD_PARAMS* params = malloc(sizeof(SERVICE_THREAD_PARAMS));
            params->action = true;
            params->pcJson = strdup(pcJson);

            //由于实际业务执行耗时较长，且会影响setFullReport本身的响应，所以起线程执行业务
            pthread_t thread;
            pthread_attr_t attr;
            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	
            if(pthread_create(&thread, &attr, service_start_stop_pthread, params) != 0)
            {

                free(params->pcJson);
                free(params);
            }
            pthread_attr_destroy(&attr);


            //char uuid[64] = { 0 };
            //GF_GetGUID(uuid);
            //dzlog_info("terminalserviceEvent start");
            //int ret = terminalserviceEvent(uuid, g_mqtt_ob.clientInfo.device_id, 1); // 系统运行数据上报
            //dzlog_info("terminalserviceEvent end");
        }
        else if (strstr(cmd, "stopService"))
        {
            SERVICE_THREAD_PARAMS* params = malloc(sizeof(SERVICE_THREAD_PARAMS));
            params->action = false;
            params->pcJson = strdup(pcJson);

            //由于实际业务执行耗时较长，且会影响setFullReport本身的响应，所以起线程执行业务
            pthread_t thread;
            pthread_attr_t attr;
            pthread_attr_init(&attr);
            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

            if(pthread_create(&thread, &attr, service_start_stop_pthread, params) != 0)
            {
                free(params->pcJson);
                free(params);
            }
            pthread_attr_destroy(&attr);
        }
        else if (strstr(cmd, "setNetworkWhitelist"))
        {
            //setFireWallList(pcJson, "ACCEPT");
        }
        else if (strstr(cmd, "setNetworkBlacklist"))
        {
           // setFireWallList(pcJson, "DROP");
        }
        else if (strstr(cmd, "disableNetworkPort"))
        {
            setNIC(pcJson, "DROP");
        }
        else if (strstr(cmd, "enableNetworkPort"))
        {
            setNIC(pcJson, "ACCEPT");
        }
        else if (strstr(cmd, "setNetworkPolicy"))
        {
            setNetworkPolicy(pcJson);
        }
        else if (strstr(cmd, "getNetworkPolicy"))
        {
            getNetworkPolicy(pcJson);
        }
        //安全加固
        else if (strstr(cmd, "setPolicySecurity"))
        {
            setPolicySecurity(pcJson);
        }
        else if (strstr(cmd, "getPolicySecurity"))
        {
            getPolicySecurity(pcJson);
        }
        // else if (strstr(cmd, "setSsh"))
        // {
        //     setPolicySecuritySsh(pcJson);
        // }
        // else if (strstr(cmd, "getSshInfo")){
        //     getPolicySecurityInfo(pcJson);   
        // }
        else if (strstr(cmd, "setVideoForwardInfo"))
        {
            setPolicySecurityVideo(pcJson);
        }
        else if (strstr(cmd, "getVideoForwardInfo"))
        {
            getPolicySecurityVideo(pcJson);
        }
        else if (strstr(cmd, "firewallOps"))
        {
            firewallOps(pcJson);
            system("iptables -S > ./conf/iptables_bak.txt");
        }
        else if (strstr(cmd, "uploadRuleset"))
        {
            uploadRuleset(pcJson);
            system("iptables -S > ./conf/iptables_bak.txt");
        }
        else if (strstr(cmd, "swapFirewall"))
        {
            swapFirewall(pcJson);
            system("iptables -S > ./conf/iptables_bak.txt");
        }

        cJSON_Delete(json);
    }
    return 0;
}
/**
 * @brief 重启后需要运行的命令
 *
 */
void commond_init_run()
{
    //每次鹰眼重启，清空规则表，再重新将备份的写入
    //判断备份规则表文件是否存在
    const char* filename = "./conf/iptables_bak.txt";
    struct stat buffer;
    // 成功返回0，失败返回-1（文件不存在或不可访问）
    if (stat(filename, &buffer) == 0) {
        printf("./conf/iptables_bak.txt文件存在\n");
        //查询系统iptables规则表得到ipt_entries
        char iptables_rules[50][512];
        int rule_count = 0;
        if ((rule_count = read_iptables_rules(iptables_rules, 50, "./conf/iptables_bak.txt")) < 0) {
            fprintf(stderr, "Error reading iptables rules\n");
            dzlog_info("commond_init_run start 3");
            return;
        }
        //// 清理规则
        system("iptables -F");
        // 重新载入防火墙规则
        // 逐条添加规则
        int i = 0;
        for (i = 0; i < rule_count; i++)
        {
            if (strncmp(iptables_rules[i], "-A ", 3) == 0) {
                // 构造iptables命令
                char command[256] = { 0 };
                snprintf(command, sizeof(command), "iptables %s", iptables_rules[i]);
                dzlog_info("commond_init_run start 6 command[%s]", command);
                // 执行命令
                if (system(command) != 0) {
                    fprintf(stderr, "Failed to execute: %s", command);
                    dzlog_info("commond_init_run start 7");
                }
            }
        }
    }
    else {
        printf("文件不存在\n");
        dzlog_info("commond_init_run start 8");
    }

    //第一版----废弃
    //int num = SqlSearNetworkPolicyCOUNT();
    //dzlog_info("commond_init_run start num[%d]", num);
    //PIOTA_NETWORKLIST_PARAM_V1 inputpar = (PIOTA_NETWORKLIST_PARAM_V1)malloc(sizeof(IOTA_NETWORKLIST_PARAM_V1) * (num + 1));
    //num = SqlSearNetworkPolicy(inputpar);
    //int i = 0;
    //for (i = 0; i < num; i++)
    //{
    //    if (setFirewallRule_V1(inputpar[i], inputpar[i].operation) >= 0)
    //    {

    //        strcpy(inputpar[i].operation, "ADD");
    //    }
    //}
    //for (i = 0; i < num; i++)
    //{
    //    if (setFirewallRule_V1(inputpar[i], inputpar[i].operation) >= 0)
    //    {
    //    }
    //}
    //free_s(inputpar);
}
